DEV Community

Cover image for go:generate 102
Francesco Di Donato
Francesco Di Donato

Posted on

go:generate 102

Like everything in existence, a generator is a function that (eventually) takes input and (eventually) returns output.

support code

Setup

I will assume from this post on that go mod init have been executed (if not see 101).

terminal

touch main.go division.generator.go
Enter fullscreen mode Exit fullscreen mode

main.go

package main

//go:generate go run division.generator.go 12 4

import "fmt"

func main() {}
Enter fullscreen mode Exit fullscreen mode

NOTE: Adding the suffix *.generator.go it's not part of the convention it's something I do.

division.go

//go:build ignore

package main

import (
    "fmt"
    "os"
    "strconv"
)

func main() {
    args := os.Args

    invoker := os.Getenv("GOFILE") // injected since it is executed via go:generate

    numerator, _ := strconv.Atoi(args[1])
    denominator, _ := strconv.Atoi(args[2])

    fmt.Println("args", args)
    fmt.Println("invoker", invoker)
    fmt.Printf("%d / %d = %d\n", numerator, denominator, numerator/denominator)
}

Enter fullscreen mode Exit fullscreen mode

Usage

terminal

go generate ./...
Enter fullscreen mode Exit fullscreen mode

output

args [path/to/exe/division.generator 12 4]
invoker main.go
12 / 4 = 3
Enter fullscreen mode Exit fullscreen mode

A lot of env variables

GOFILE is not the only env variable provided.

for _, ev := range []string{"GOARCH", "GOOS", "GOFILE", "GOLINE", "GOPACKAGE", "DOLLAR"} {
    fmt.Println(ev, os.Getenv(ev))
}
Enter fullscreen mode Exit fullscreen mode

terminal

GOARCH arm64
GOOS darwin
GOFILE main.go
GOLINE 3 // lineno of //go:generate 
GOPACKAGE main
DOLLAR $
Enter fullscreen mode Exit fullscreen mode

Reuse across different projects

It is necessary to build the generator and place it in the GOPATH.

terminal

go build -o division division.generator.go
mv ./division $GOPATH/bin
Enter fullscreen mode Exit fullscreen mode

main.go

package main

//go:generate division 12 4

import "fmt"

func main() {}
Enter fullscreen mode Exit fullscreen mode

NOTE: No go run, just the name of the executable.

References

Top comments (0)