Saltar al contenido

Literales de Struct

Los literales de struct te dan el control más directo sobre la creación de recursos. Inicializas los campos del struct Go explícitamente, lo cual es familiar para cualquier desarrollador Go y proporciona verificación completa de tipos en tiempo de compilación.

Ejemplo Básico

package main

import (
    "fmt"

    "github.com/gofhir/models/r4/v2"
)

func main() {
    patient := r4.Patient{
        Id:           ptrTo("123"),
        Active:       ptrTo(true),
        Name: []r4.HumanName{
            {Family: ptrTo("Smith"), Given: r4.PtrSlice("John")},
        },
    }

    data, _ := r4.Marshal(&patient)
    fmt.Println(string(data))
}
No hay ningún resourceType que rellenar. El campo es un tipo marcador de tamaño cero, así que r4.Patient{} ya se serializa como {"resourceType":"Patient",...}, y asignarlo no es posible. Léelo con GetResourceType().

Manejo de Punteros

En FHIR, la mayoría de los campos primitivos son opcionales. Los structs Go representan esto con tipos puntero (*string, *bool, *int). No puedes tomar la dirección de un valor literal directamente en Go, por lo que necesitas un patrón auxiliar.

El Auxiliar ptrTo

El enfoque más común es una función auxiliar genérica:

func ptrTo[T any](v T) *T {
    return &v
}

La librería ya los incluye.

No hace falta escribir el suyo. Cada paquete de versión exporta Ptr, PtrSlice, Val y First:

Id:     r4.Ptr("patient-1"),
Given:  r4.PtrSlice("John", "Michael"),   // []*string en una llamada
family: r4.Val(name.Family),              // *string -> string, "" si es nil
first:  r4.First(patient.Name),           // primer elemento o el valor cero

PtrSlice importa en los primitivos repetidos, que son []*string y no []string para poder representar un null posicional: un literal []string no compila ahí. Los ejemplos de esta guía usan ptrTo para que cada fragmento se sostenga por sí solo.

Esto funciona con cualquier tipo:

patient := r4.Patient{
    Id:        ptrTo("patient-1"),
    Active:    ptrTo(true),
    BirthDate: ptrTo("1990-05-15"),
    Gender:    ptrTo(r4.AdministrativeGenderMale),
}

Variables Locales

Alternativamente, puedes usar variables locales y tomar su dirección:

id := "patient-1"
active := true
gender := r4.AdministrativeGenderFemale

patient := r4.Patient{
    Id:     &id,
    Active: &active,
    Gender: &gender,
}

Este enfoque es útil cuando necesitas reutilizar valores o cuando el tipo del campo es un tipo personalizado de sistema de códigos.

Recursos Complejos

Los literales de struct funcionan bien para construir recursos con tipos de datos anidados:

system := "http://hospital.example.org/mrn"
value := "MRN-12345"
use := r4.NameUseOfficial
family := "Johnson"
homeUse := r4.AddressUseHome

patient := r4.Patient{
    Id:     ptrTo("patient-complex"),
    Active: ptrTo(true),
    Identifier: []r4.Identifier{
        {
            System: &system,
            Value:  &value,
        },
    },
    Name: []r4.HumanName{
        {
            Use:    &use,
            Family: &family,
            Given:  r4.PtrSlice("Robert", "James"),
        },
    },
    Gender:    ptrTo(r4.AdministrativeGenderMale),
    BirthDate: ptrTo("1978-11-03"),
    Address: []r4.Address{
        {
            Use:        &homeUse,
            Line:       r4.PtrSlice("123 Main St", "Apt 4B"),
            City:       ptrTo("Springfield"),
            State:      ptrTo("IL"),
            PostalCode: ptrTo("62704"),
            Country:    ptrTo("US"),
        },
    },
    Telecom: []r4.ContactPoint{
        {
            System: ptrTo(r4.ContactPointSystemPhone),
            Value:  ptrTo("555-0123"),
            Use:    ptrTo(r4.ContactPointUseHome),
        },
        {
            System: ptrTo(r4.ContactPointSystemEmail),
            Value:  ptrTo("robert.johnson@example.com"),
        },
    },
}

Observations con Literales de Struct

codeSystem := "http://loinc.org"
codeCode := "8480-6"
codeDisplay := "Systolic blood pressure"
unitSystem := "http://unitsofmeasure.org"

obs := r4.Observation{
    Status: ptrTo(r4.ObservationStatusFinal),
    Code: &r4.CodeableConcept{
        Coding: []r4.Coding{
            {
                System:  &codeSystem,
                Code:    &codeCode,
                Display: &codeDisplay,
            },
        },
    },
    ValueQuantity: &r4.Quantity{
        Value:  r4.NewDecimalFromFloat64(120.0),
        Unit:   ptrTo("mmHg"),
        System: &unitSystem,
        Code:   ptrTo("mm[Hg]"),
    },
    EffectiveDateTime: ptrTo("2024-01-15T10:30:00Z"),
}

Cuándo Usar Literales de Struct

Los literales de struct son una buena elección cuando:

  • Quieres visibilidad completa de cada campo que se establece.
  • Estás construyendo un recurso a partir de un conjunto conocido y fijo de valores (como fixtures de prueba o datos semilla).
  • Prefieres los modismos explícitos de Go sobre las abstracciones de builders.

Para situaciones donde el código repetitivo de punteros es engorroso, considera el Patrón Builder en su lugar.

Última actualización