CUE v0.12.0 introduced an experimental new command:
gengotypes.
This command generates Go types from CUE definitions and places them in .go
files. It uses sensible defaults for the generated Go code that you can
override by configuring various CUE attributes.
This guide shows you how to use the cue exp gengotypes command.
Why was gengotypes introduced?
When a Go program works with CUE it can be useful to declare Go types which mirror its CUE schemas.
For example, if the program loads a YAML configuration file and validates it using a CUE schema it’s often useful to hold the config as a Go struct value that controls how the program should behave.
Using gengotypes allows you to declare your schemas in CUE and automatically
derive compatible Go types – without having to repeat yourself or maintain two
versions of the same structure.
Generating Go types
Start with some CUE that contains at least one definition:
package pet
// These are the only pet types we can handle.
petTypes: ["dog", "cat", "goldfish"]
// A dog tracks information we hold about each dog.
#dog: {
	// A dog has at least one name.
	name!: string
	age?:  float & <30
}Hidden definitions (fields with names that start _#) are ignored by the
gengotypes command.
Run the cue exp gengotypes command targetting the single CUE package in the
current directory:
$ cue exp gengotypes .The command is silent when it succeeds.
Observe the contents of the cue_types_pet_gen.go file:
// Code generated by "cue exp gengotypes"; DO NOT EDIT.
package pet
// A dog tracks information we hold about each dog.
type Dog struct {
	// A dog has at least one name.
	Name string `json:"name"`
	Age float64 `json:"age,omitempty"`
}Notice these differences between the contents of
pets.cue
and
cue_types_pet_gen.go:
- By default, gengotypesensures the first character of each struct’s name is upper-cased (#dogvsDog).
- The top-level regular field petTypesand its comment aren’t present in the Go file. Only fields inside a definition are translated to Go.
- The optional field agehas a numeric constraint in CUE (<30) which can’t be expressed in the simpler, less powerful Go type system – so the Go encodes afloat64type. Generated Go types are guaranteed to accept any value accepted by the CUE definitions but, as withage, they may be more general.
Controlling the generated Go
If you need to control the generated Go package, type, and field names, you can
use the @go() attribute to specify them in your CUE:
Add another CUE file, morePets.cue, containing the following code:
package pet
@go(acmecorppets) // Rename this package when emitted as Go.
// A cat represents an instance of a domestic cat.
#cat: {
	@go(cat) // Rename this definition when emitted as Go.
	// Cats consider themselves to have a title, not a name.
	title!:              string @go(Name) // Rename this field when emitted as Go
	socialMediaAccount!: string @go(-)    // Don't emit this field as Go.
}
#horse: {
	@go(-) // Don't emit this definition as Go.
	status: "Unsupported"
}Run the cue exp gengotypes command again:
$ cue exp gengotypes .Observe the new contents of the cue_types_pet_gen.go file:
// Code generated by "cue exp gengotypes"; DO NOT EDIT.
package acmecorppets
// A cat represents an instance of a domestic cat.
type cat struct {
	// Cats consider themselves to have a title, not a name.
	Name string `json:"title"`
}
// A dog tracks information we hold about each dog.
type Dog struct {
	// A dog has at least one name.
	Name string `json:"name"`
	Age float64 `json:"age,omitempty"`
}Notice these differences between the contents of
morePets.cue
and the new
cue_types_pet_gen.go:
- At the package level:- The @go(acmecorppets)attribute renamed the generated Go package frompet.
- The cuecommand targetted the whole of the CUE package so the dog-related contents ofpets.cueare included under the renamed Go package. Only a single package-level renaming attribute is needed.
 
- The 
- Inside #cat:- The definition-level @go(cat)attribute renamed the generated Go type from the default that would otherwise have been emitted (Cat).
- The field-level @go(Name)attribute renamed the generated Go field fromTitle.
- The field-level @go(-)attribute caused thesocialMediaAccountfield to be omitted from the generated Go type.
 
- The definition-level 
- Inside #horse, the definition-level@go(-)attribute caused the entire definition to be omitted from the generated Go.
You can also use the @go() attribute to control the type of a generated
field – see
cue help exp gengotypes
for more information.
gengotypes command is still in an experimental stage, which means that it
may be changed or removed at any time. The objective is for the CUE project to
gain experience through your feedback about this
experimental command, and then move the feature elsewhere.Related content
- Reference: cue help exp gengotypes –
the built-in help text for the cue exp gengotypescommand
