Standard library

Built-in templates

Metago embeds its standard templates in the binary. They work without local .metago files and use the reserved std. namespace, which user templates cannot define.

TemplateGenerates
std.stringerA String method for primitive-backed types.
std.enumString conversion, parsing, validation, values, and JSON for enums.
std.mockFunction-backed mocks for interfaces.
std.mapstructTyped struct-to-map encoding and decoding.
std.serdeReflection-free JSON codecs.
std.serde.jsonruntimeThe shared, project-owned runtime used by std.serde.

std.stringer

Generate String() string for a primitive-backed defined type:

//mgo:gen std.stringer trimprefix=Status
type Status int

const (
    StatusPending Status = iota
    StatusRunning
    StatusDone
)

Declared typed constants become switch cases:

func (v Status) String() string {
    switch v {
    case StatusPending:
        return "Pending"
    case StatusRunning:
        return "Running"
    case StatusDone:
        return "Done"
    default:
        return "Status(" + strconv.FormatInt(int64(v), 10) + ")"
    }
}

Supported underlying types are string, bool, signed and unsigned integers, floats, and complex numbers. Unknown values use Type(value); unknown strings are quoted.

ArgumentDefaultBehavior
trimprefix=valueNo trimmingRemoves the prefix from constant names returned by String.

The target must be primitive-backed. Other targets fail generation.

std.enum

Generate the conventional enum API from a defined type and its typed constants:

//mgo:gen std.enum
type Status int

const (
    StatusPending Status = iota
    StatusRunning
    StatusDone
)

The generated API is:

func (v Status) String() string
func ParseStatus(value string) (Status, error)
func (v Status) Valid() bool
func StatusValues() []Status
func (v Status) MarshalJSON() ([]byte, error)
func (v *Status) UnmarshalJSON(data []byte) error

Supported underlying types are strings, signed integers, unsigned integers, and floats. The type must have at least one discovered typed constant.

Integer and float enums strip the type name from constant names by default. String enums use each constant’s string value. JSON uses the same string form and rejects unknown values.

ArgumentDefaultBehavior
trimprefix=valueThe target type nameChanges the prefix removed from integer and float constant names.

std.mock

Generate a function-backed mock for an interface:

//mgo:gen std.mock
type Store interface {
    Get(id string) (User, error)
    Save(user User) error
}

The generated mock has one function field per discovered method and forwarding methods that satisfy the interface:

type MockStore struct {
    GetFunc  func(id string) (User, error)
    SaveFunc func(user User) error
}

func (m *MockStore) Get(id string) (User, error) {
    return m.GetFunc(id)
}

func (m *MockStore) Save(user User) error {
    return m.SaveFunc(user)
}

Assign the function fields directly in tests:

store := &MockStore{
    GetFunc: func(id string) (User, error) {
        return User{ID: id}, nil
    },
    SaveFunc: func(user User) error {
        return nil
    },
}

Interface method parameters should be named. Embedded interface methods are not expanded, and variadic forwarding is not specially handled.

std.mapstruct

Generate typed conversion between a struct and map[string]any:

//mgo:gen std.mapstruct allowmissing
type Config struct {
    Host string `mapstructure:"host,required"`
    Port int    `mapstructure:"port"`
}

The generated API is:

func (v *Config) Decode(input map[string]any) error
func (v *Config) Encode() map[string]any

The template:

  • Operates on exported fields.
  • Uses mapstructure tag names.
  • Ignores mapstructure:"-" fields.
  • Recurses into local named struct fields.
  • Requires nested inputs to be map[string]any.
  • Uses exact Go type assertions instead of numeric or string conversions.
  • Decodes transactionally, updating the receiver only after every field succeeds.

By default every included field is required. The positional allowmissing flag makes fields optional unless their mapstructure tag contains required.

var config Config
err := config.Decode(map[string]any{
    "host": "127.0.0.1",
    "port": 8080,
})

encoded := config.Encode()

std.serde

Generate reflection-free MarshalJSON and UnmarshalJSON methods plus package-private helpers:

//mgo:gen std.serde
type User struct {
    ID   int64    `json:"id"`
    Name string   `json:"name"`
    Tags []string `json:"tags,omitempty"`
}

Generated paths cover built-in and methodless named scalars, pointers, slices, arrays, bytes, json.RawMessage, string-keyed maps, nested generated types, and common combinations of those shapes.

Unsupported field shapes fall back per field to encoding/json, preserving support for json.Marshaler, json.Unmarshaler, encoding.TextMarshaler, and encoding.TextUnmarshaler. Anonymous fields use a whole-struct encoding/json fallback so Go’s promotion and dominance rules remain canonical.

Serde follows encoding/json behavior for field names and visibility, -, omitempty, omitzero, and supported string options. Decode failures are transactional, and retained decoded strings do not alias the input. Recursive generated pointers and containers detect cycles during encoding. Errors include field, Go type, JSON kind, and offset context.

ArgumentDefaultBehavior
runtime=import/pathSame packageImports the generated runtime using the internal alias serdejsonruntime.
strict=true|falsefalseRejects unknown object fields when true. Otherwise unknown values are skipped after full syntax validation.
maxinput=NDisabledRejects input larger than N bytes before receiver-state allocation. Zero disables the cap.
maxdepth=N10000Sets the maximum JSON nesting depth. Zero keeps the default.

strict accepts only true or false. maxinput and maxdepth must be unsigned 64-bit decimal integers. Invalid values fail generation. Directive-local arguments override defaults from metago.toml.

Shared runtime

For larger projects, generate the runtime once in a dedicated package:

// Package jsonruntime contains generated JSON support.
//
//mgo:gen std.serde.jsonruntime
package jsonruntime

Then configure its import path:

[templates."std.serde".args]
runtime = "example.com/project/internal/jsonruntime"

Nested generated types call one another directly. Every package deriving codecs should resolve the same runtime import.

Without a runtime argument, codecs expect std.serde.jsonruntime to be generated in the same package.

std.serde.jsonruntime

This package-scoped template emits the shared lexer and marshal helpers used by std.serde. Its output is ordinary, project-owned Go code; there is no external runtime library.

Use it once per runtime package:

//mgo:gen std.serde.jsonruntime
package jsonruntime

It emits the JSON lexer, append helpers, syntax validation, nesting-depth accounting, retained-string arena, and contextual error support. Application code normally interacts with the generated MarshalJSON and UnmarshalJSON methods rather than calling runtime helpers directly.

For compatibility policy, reliability tests, and benchmarks, see the std/serde implementation notes.