Code generation writes Go source from inputs such as type names or annotated structs, then compiles that source with the rest of the program. It is useful when repeated declarations would be tedious or when runtime reflection adds latency and allocations. Generics remain an option; generation has a niche when they do not fit the task. section 13.3 section 13.0
To run a generator, place a directive such as `//go:generate ./queue MyInt` in a Go file and run `go generate`. The command is an executable plus arguments: `go generate` finds the directive and runs it. A generator can read those arguments, obtain the package name from `GOPACKAGE`, and write a `.go` file. section 13.3
Listing 13.19 The queue template
package main
import (
"fmt"
"os"
"strings"
"text/template"
)
var tpl = `package {{.Package}} #1
type {{.MyType}}Queue struct { #2
q []{{.MyType}}
}
func New{{.MyType}}Queue() *{{.MyType}}Queue {
return &{{.MyType}}Queue{
q: []{{.MyType}}{},
}
}
func (o *{{.MyType}}Queue) Insert(v {{.MyType}}) {
o.q = append(o.q, v)
}
func (o *{{.MyType}}Queue) Remove() {{.MyType}} {
if len(o.q) == 0 {
panic("Oops.")
}
first := o.q[0]
o.q = o.q[1:]
return first
}
The queue template substitutes a package name and type name into a struct, constructor, and methods. section 13.3
Listing 13.20 The main queue generator
func main() {
tt := template.Must(template.New("queue").Parse(tpl)) #1
for i := 1; i < len(os.Args); i++ { #2
dest := strings.ToLower(os.Args[i]) +
"_queue.go"
file, err := os.Create(dest)
if err != nil {
fmt.Printf("Could not create %s: %s (skip)\n",
dest, err)
continue
}
vals := map[string]string{
"MyType": os.Args[i], #3
"Package": os.Getenv("GOPACKAGE"), #4
}
tt.Execute(file, vals) #5
file.Close()
}
}
The generator loops over type-name arguments and writes a separate queue source file for each. section 13.3
Generate a typed queue
With `type MyInt int` and `//go:generate ./queue MyInt` in `myint.go`, running `go generate` creates `myint_queue.go`. Compile both files to use `NewMyIntQueue`, `Insert`, and `Remove`; the demonstrated program removes the first inserted value. section 13.3
Generation can also move repeated type inspection out of a hot path. The `codecgen` command reads a tagged `User` struct and produces `CodecEncodeSelf` and `CodecDecodeSelf` methods. The codec package uses those methods when present and otherwise falls back to runtime handling. This can reduce the reflection costs of repeated JSON encoding and decoding. section 12.3.1
Other uses include generating protocol-buffer and gRPC scaffolding from service definitions. That saves hand-written message-handling code, though adopting gRPC can be more involved than building a small REST API. section 11.5
















