Skip to content

Struct Literals

Struct literals give you the most direct control over resource creation. You initialize the Go struct fields explicitly, which is familiar to any Go developer and provides full compile-time type checking.

Basic Example

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))
}
There is no resourceType to fill in. The field is a zero-size marker type, so r4.Patient{} already serializes as {"resourceType":"Patient",...}, and assigning it is not possible. Read it with GetResourceType().

Handling Pointers

In FHIR, most primitive fields are optional. The Go structs represent this with pointer types (*string, *bool, *int). You cannot take the address of a literal value directly in Go, so you need a helper pattern.

The ptrTo Helper

The most common approach is a generic helper function:

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

The library already ships these.

You do not have to write your own. Each version package exports Ptr, PtrSlice, Val and First:

Id:     r4.Ptr("patient-1"),
Given:  r4.PtrSlice("John", "Michael"),   // []*string in one call
family: r4.Val(name.Family),              // *string -> string, "" if nil
first:  r4.First(patient.Name),           // first element or the zero value

PtrSlice matters for repeating primitives, which are []*string rather than []string so a positional null can be represented — a []string literal will not compile there. The examples in this guide use ptrTo to keep each snippet self-contained.

This works with any type:

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

Local Variables

Alternatively, you can use local variables and take their address:

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

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

This approach is useful when you need to reuse values or when the field type is a custom code system type.

Complex Resources

Struct literals work well for building resources with nested data types:

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 with Struct Literals

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"),
}

When to Use Struct Literals

Struct literals are a good choice when:

  • You want full visibility into every field being set.
  • You are building a resource from a known, fixed set of values (such as test fixtures or seed data).
  • You prefer explicit Go idioms over builder abstractions.

For situations where pointer boilerplate is cumbersome, consider the Builder Pattern instead.

Last updated on