pinfomap
Description
Generates Go code from a template by referencing package information such as package names, imports, and struct fields.
Examples
Accessor Generation
./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.