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))
}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 ceroPtrSlice 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.