Generates Go code from a template by referencing package information such as package names, imports, and struct fields.
./foo.go
contains the sample struct Foo
:
package examples
import (
goimports "github.com/incu6us/goimports-reviser/v3/reviser"
"text/template"
)
type Foo struct {
bar string `accessor:"setter,getter=true"`
Baz int
qux template.Template `accessor:"getter,setter=false"`
quux *goimports.SourceDir `accessor:"setter"`
}
./gen_foo_accessor_go/main.go
serves as an accessor generator for the struct. You can place the generator comment //go:generate go run ./gen_foo_accessor_go/
in the same directory as ./foo.go
:
package main
import (
"github.com/knaka/go-pinfomap"
"github.com/knaka/go-pinfomap/examples"
"github.com/knaka/go-pinfomap/generator"
"log"
)
func main() {
// Extracts information about a struct by passing an instance of the struct.
// Here, we're using 'examples.Foo{}' with an option to include fields tagged as "accessor".
structInfo, err := pinfomap.NewStructInfo(examples.Foo{}, pinfomap.WithTags("accessor"))
if err != nil {
log.Fatalf("failed to get struct info: %v", err)
}
// You can also specify a struct by its name to extract information.
// Use just the name "Foo" for structs in the current package or provide the full path
// like "github.com/knaka/foo/bar.baz" for the other structs.
// This approach is useful for accessing structs dynamically or when they're not directly accessible.
_, err = pinfomap.NewStructInfo("Foo", pinfomap.WithTags("accessor"))
if err != nil {
log.Fatalf("failed to get struct info: %v", err)
}
// Adding additional data to the 'structInfo' which can be utilized in the template.
structInfo.Data = map[string]any{
"AdditionalComment": "This is a comment.",
}
// Generates Go code based on the 'AccessorTemplate' and the provided 'structInfo'.
err = generator.GenerateGo(pinfomap.AccessorTemplate, structInfo)
if err != nil {
log.Fatalf("failed to generate go: %v", err)
}
}
Running go run ./gen_foo_accessor_go/
will generate the following code as ./foo_accessor.go
:
// Code generated by gen_foo_accessor_go; DO NOT EDIT.
package examples
import (
"text/template"
"github.com/incu6us/goimports-reviser/v3/reviser"
)
func (rcv *Foo) GetBar() string {
return rcv.bar
}
func (rcv *Foo) SetBar(value string) {
rcv.bar = value
}
func (rcv *Foo) GetQux() template.Template {
return rcv.qux
}
func (rcv *Foo) SetQuux(value *reviser.SourceDir) {
rcv.quux = value
}
Running go run ./gen_foo_accessor_go.go
is also feasible if you prefer to place the generator code in the same directory as ./foo.go
. Be sure to add //go:build ignore
to the top of the generator's code to prevent it from being compiled and linked with other code.
While the above example is using the template AccessorTemplate
, you can use your own template by passing it to pinfomap.Generate
. The AccessorTemplate
is defined as follows:
{{- /* gotype: github.com/knaka/go-pinfomap.Struct */ -}}
// Code generated by {{GeneratorName}}; DO NOT EDIT.
package {{.Package.Name}}
import (
{{- range .Imports }}
"{{.}}"
{{- end }}
)
{{- $structName := .StructName }}
{{- range .PrivateFields }}
{{- if .Params.getter }}
func (rcv *{{$structName}}) Get{{.CapName}}() {{.Type}} {
return rcv.{{.Name}}
}
{{- end }}
{{- if .Params.setter }}
func (rcv *{{$structName}}) Set{{.CapName}}(value {{.Type}}) {
rcv.{{.Name}} = value
}
{{- end }}
{{- end }}
The resulting Go code is automatically formatted with goimports-reviser, allowing you to write the template without worrying about the strictness of import statements or unnecessary empty lines.