Multi-Version Support
The gofhir/models repository publishes each FHIR version as an independent Go module. This architecture allows you to import a single version, or import multiple versions in the same project without conflicts.
Module Structure
Each FHIR version lives in its own directory at the repository root with its own go.mod:
models/
go.work # Go workspace file for local development
r4/
go.mod # module github.com/gofhir/models/r4/v2
helpers/ # Hand-written helper constants
r4b/
go.mod # module github.com/gofhir/models/r4b/v2
r5/
go.mod # module github.com/gofhir/models/r5/v2The root go.work file ties these modules together for local development:
go 1.23
use (
./cmd/generator
./r4
./r4b
./r5
)Importing a Single Version
Most projects only need one FHIR version. Import the corresponding module directly:
import "github.com/gofhir/models/r4/v2"
patient := r4.NewPatientBuilder().
SetId("example").
Build()Install with:
go get github.com/gofhir/models/r4/v2Importing Multiple Versions
When you need to work with multiple FHIR versions (for example, a converter or a server that supports multiple versions), import them with package aliases:
import (
r4 "github.com/gofhir/models/r4/v2"
r5 "github.com/gofhir/models/r5/v2"
)
func convertPatient(r4Patient *r4.Patient) *r5.Patient {
r5Patient := r5.NewPatientBuilder().
SetId(*r4Patient.Id).
SetBirthDate(*r4Patient.BirthDate).
Build()
// Copy names
for _, name := range r4Patient.Name {
r5Patient.Name = append(r5Patient.Name, r5.HumanName{
Family: name.Family,
Given: name.Given,
})
}
return r5Patient
}Install both modules:
go get github.com/gofhir/models/r4/v2
go get github.com/gofhir/models/r5/v2r4.Patient and an r5.Patient are distinct types, even though they share the same struct name within their packages.Package Aliasing Patterns
When importing multiple versions, the default package name matches the directory name (r4, r4b, r5), so aliasing is only necessary if you want custom names:
import (
// Default names -- no alias needed
"github.com/gofhir/models/r4/v2"
"github.com/gofhir/models/r4b/v2"
"github.com/gofhir/models/r5/v2"
)
// Or use descriptive aliases
import (
fhirR4 "github.com/gofhir/models/r4/v2"
fhirR4B "github.com/gofhir/models/r4b/v2"
fhirR5 "github.com/gofhir/models/r5/v2"
)Independent Versioning
Each module is versioned independently using release-please. This means:
- A bug fix in the R4 module does not force a version bump in R4B or R5
- Breaking changes in one version package do not affect others
- Each module has its own
CHANGELOG.mdtracking changes
Version tags follow the pattern <component>/v<version>:
r4/v0.3.0
r4b/v0.2.1
r5/v0.1.0The release-please-config.json at the repository root configures this multi-package release strategy:
{
"packages": {
"r4": {
"release-type": "go",
"component": "r4",
"changelog-path": "CHANGELOG.md"
},
"r4b": {
"release-type": "go",
"component": "r4b",
"changelog-path": "CHANGELOG.md"
},
"r5": {
"release-type": "go",
"component": "r5",
"changelog-path": "CHANGELOG.md"
}
}
}Version-Specific Features
While the three packages share the same overall structure, each FHIR version has differences in its resource set and data types. For example:
- R4 includes resources like
MedicinalProductandEffectEvidenceSynthesisthat were removed in R5 - R4B is largely identical to R4 with incremental updates to certain resources
- R5 introduces new resources and refactors others (e.g., the medication-related resources were restructured)
The generated code for each version precisely reflects the official StructureDefinitions for that FHIR release, so you always get the correct type definitions for the version you are targeting.
Go Workspace for Development
If you are contributing to the gofhir/models project itself, the go.work file allows all modules to be developed together without publishing. The workspace ensures that local changes to shared infrastructure (like the generator) are immediately visible across all version packages.
# Run all R4 tests
cd r4 && go test ./...
# Run all R4B tests
cd r4b && go test ./...
# Run all R5 tests
cd r5 && go test ./...The go.work file is not included in published modules and does not affect downstream consumers.