Enum stringer
Use the embedded template when you need the conventional implementation:
package status
//mgo:gen std.stringer trimprefix=Status
type Status int
const (
StatusPending Status = iota
StatusRunning
StatusDone
)
Running metago . generates String() string. For unknown values it returns Status(value).
A custom template gives you complete control:
{{ define "short-status" }}
func (v {{ name . }}) String() string {
switch v {
{{- range .Values }}
case {{ .Name }}:
return {{ quote (trimPrefix .Name "Status") }}
{{- end }}
default:
return "unknown"
}
}
{{ end }}
//mgo:gen short-status
type Status int
Interface mock
package users
//mgo:gen std.mock
type Store interface {
Find(id string) (User, error)
Save(user User) error
}
Metago generates a MockStore with one function field per method:
func TestService(t *testing.T) {
store := MockStore{
FindFunc: func(id string) (User, error) {
return User{ID: id}, nil
},
SaveFunc: func(user User) error {
return nil
},
}
service := NewService(store)
// ...
}
Use named, non-variadic interface parameters. Embedded interface methods are not expanded by the standard mock template.
Reflection-free JSON
Generate the runtime once:
// Package jsonruntime contains generated JSON support.
//
//mgo:gen std.serde.jsonruntime
package jsonruntime
Set the runtime import for every codec in metago.toml:
[templates."std.serde".args]
runtime = "example.com/project/internal/jsonruntime"
strict = "true"
maxinput = "1048576"
Derive codecs on models:
package users
//mgo:gen std.serde
type User struct {
ID int64 `json:"id"`
Name string `json:"name"`
Tags []string `json:"tags,omitempty"`
Address Address `json:"address"`
}
//mgo:gen std.serde
type Address struct {
City string `json:"city"`
}
The generated types implement json.Marshaler and json.Unmarshaler. Unsupported field shapes fall
back to encoding/json for that field.
Validation properties
Properties attach generator-specific metadata to a declaration:
//mgo:gen validate
type Signup struct {
Email string `json:"email"` //mgo:validate required format=email
Name string `json:"name"` //mgo:validate required max=80
Age int `json:"age"` //mgo:validate min=18
}
{{ define "validate" }}
func (v {{ name . }}) Validate() error {
{{- range .Fields }}
{{- if propHas . "validate" "required" }}
if v.{{ .Name }} == {{ zero . }} {
return fmt.Errorf({{ quote (printf "%s is required" (tagName . "json")) }})
}
{{- end }}
{{- end }}
return nil
}
{{ imports "fmt" }}
{{ end }}
The imports call can appear after the generated code; it records the import and emits no text.
Package registry
One aggregate invocation can inspect marker directives across a package:
//mgo:gen route-table
package api
//mgo:gen route GET /users
func ListUsers() {}
//mgo:gen route POST /users
func CreateUser() {}
{{ define "route" }}{{ end }}
{{ define "route-table" }}
type Route struct {
Method string
Path string
}
var Routes = []Route{
{{- range .Package.Metas }}
{{- if eq .Template "route" }}
{Method: {{ quote (index .Argv 0) }}, Path: {{ quote (index .Argv 1) }}},
{{- end }}
{{- end }}
}
{{ end }}
route produces no code, but each //mgo:gen route ... directive still appears in
.Package.Metas. The route-table template reads those directives and generates one route table
for the package. Entries in .Package.Metas are ordered by file and line.
Inline generated code
Inline output is useful when generated declarations are easier to understand beside their source:
//mgo:inline constructor
type Client struct {
BaseURL string
Token string
}
{{ define "constructor" }}
func New{{ name . }}(
{{- range .Fields }}
{{ unexported .Name }} {{ typeof . }},
{{- end }}
) *{{ name . }} {
return &{{ name . }}{
{{- range .Fields }}
{{ .Name }}: {{ unexported .Name }},
{{- end }}
}
}
{{ end }}
Metago inserts the constructor after Client and closes the managed region with //mgo:end. Later
runs replace only that region.
Test-only generation
Directives in test files stay in test builds:
package service_test
// Clock provides time in tests.
//mgo:gen std.mock
type Clock interface {
Now() time.Time
}
For an external service_test package, Metago writes meta_service_test.go. Internal test
directives write meta_test.go. Production meta.go remains unaffected.
For exact supported targets, helper signatures, and standard-template options, use the reference.