# README
#+startup: overview #+title: gogen
- gogen golang generate tool collection and merge.
| command | source | description | |----------+------------+--------------------------------------------------------------------| | stringer | [[https://pkg.go.dev/golang.org/x/tools/cmd/stringer][stringer]] | generate fmt.Stringer interface for const integer. | | import | | import const type and value from another package. | | option | [[https://github.com/timestee/optiongen][optiongen]] | generate generate go Struct option for test, mock or more flexible | | imake | [[https://github.com/vburenin/ifacemaker][ifacemaker]] | generate interface from go struct define. mock stub supported |
** stringer #+begin_src text Usage: gogen stringer [flags] -t T [directory | files ]
Flags: -h, --help help for stringer --linecomment use line comment text as printed text when present -o, --output string output file name; default srcdir/_string.go --tags strings comma-separated list of build tags to apply -p, --trimprefix prefix trim the prefix from the generated constant names -t, --type strings list of type names; must be set #+end_src sample source code [[./samples/testdata/test.go][samples/testdata/test.go]] #+begin_src go
// TestType test type comment 1 // second line comment type TestType int // comment 2
const ( // T1 comment 11 T1 TestType = iota // line suffix comment 1 // T2 comment 22 T2 T3 // T3 line suffix comment 1 ) #+end_src
generete: [[./samples/testdata/testtype_string.go][samples/testdata/testtype_string.go]] #+begin_src go // Code generated by "gogen stringer"; DO NOT EDIT. // Exec: "gogen stringer -t TestType" // Version: 0.0.1
package testdata
import "strconv"
func _() { // An "invalid array index" compiler error signifies that the constant values have changed. // Re-run the stringer command to generate them again. var x [1]struct{} _ = x[T1-0] _ = x[T2-1] _ = x[T3-2] }
const _TestType_name = "T1T2T3"
var _TestType_index = [...]uint8{0, 2, 4, 6}
func (i TestType) String() string { if i < 0 || i >= TestType(len(_TestType_index)-1) { return "TestType(" + strconv.FormatInt(int64(i), 10) + ")" } return _TestType_name[_TestType_index[i]:_TestType_index[i+1]] }
#+end_src
** import #+begin_src text Usage: gogen import [flag] -t T [flags]
Flags: -f, --func strings list of functions names -h, --help help for import --new import type new functions -o, --output string output file name; default _import.go --tags strings comma-separated list of build tags to apply --to string which package be imported, extract the package from this folder (default ".") -p, --trimprefix prefix trim the prefix from the generated constant names -t, --type strings list of type names; must be set -v, --value strings list of value names --version version for import #+end_src sample source code [[./samples/testdata/test.go][samples/testdata/test.go]] #+begin_src go
// TestType test type comment 1 // second line comment type TestType int // comment 2
const ( // T1 comment 11 T1 TestType = iota // line suffix comment 1 // T2 comment 22 T2 T3 // T3 line suffix comment 1 ) #+end_src generate code [[./samples/gen_td.go][samples/gen_td.go]] #+begin_src go // Code generated by "gogen import"; DO NOT EDIT. // Exec: "gogen import ./testdata -t TestType" // Version: 0.0.1
package main
import testdata "github.com/aggronmagi/gogen/testdata"
// TestType test type comment 1 // second line comment type TestType = testdata.TestType // comment 2
const ( // T1 comment 11 T1 = testdata.T1 // line suffix comment 1 // T2 comment 22 T2 = testdata.T2 T3 = testdata.T3 // T3 line suffix comment 1 )
#+end_src
** option #+begin_src text Usage: gogen option [flags]
Flags: -e, --all-export Export all field option settings. If set to false, lowercase fields will not be exported. (default true) -a, --gen-slice-append decide whether generate append method for slice option. -h, --help help for option -n, --options-name string generate options name,default collection from function name. -f, --with-option-name Decide whether the name of the generated setting function has an option name, which is used to have multiple options for repetitio #+end_src sample source code #+begin_src go
// Google Public DNS provides two distinct DoH APIs at these endpoints // Using the GET method can reduce latency, as it is cached more effectively. // RFC 8484 GET requests must have a ?dns= query parameter with a Base64Url encoded DNS message. The GET method is the only method supported for the JSON API. //go:generate gogen option func ConfigOptionDeclareWithDefault() interface{} { return map[string]interface{}{ // test comment 1 // test comment 2 "TestNil": nil, // test comment 3 "TestBool": false, // test comment 4 // 这里是函数注释1 // 这里是函数注释2 "TestInt": 32, // default 32 "TestInt64": int64(32), // int64 line "TestSliceInt": []int{1, 2, 3}, // slice int "TestSliceInt64": []int64{1, 2, 3}, // slice int64 line "TestSliceString": []string{"test1", "test2"}, // slice string "TestSliceBool": []bool{false, true}, // slice bool line comment "TestSliceIntNil": []int(nil), // TestSliceIntNil line comment "TestSliceByte": []byte(nil), // TestSliceByte line comment // SliceInt Doc "TestSliceIntEmpty": []int{}, // Slice int line comment "TestMapIntInt": map[int]int{1: 1, 2: 2, 3: 3}, // TestMapIntInt line comment "TestMapIntString": map[int]string{1: "test"}, // TestMapIntString line comment "TestMapStringInt": map[string]int{"test": 1}, // TestMapStringInt line comment // MapStringString Doc "TestMapStringString": map[string]string{"test": "test"}, // MapStringString Line Comment
"TestString": "Meow",
// Food Doc
"Food": (*string)(nil), // Food Line Comment
// Walk Doc
"Walk": func() {
log.Println("Walking")
}, // Walk Line Comment
// TestNilFunc
"TestNilFunc": (func())(nil), // 中文1
// TestReserved1_
"TestReserved1_": []byte(nil), // 在调优或者运行阶段,我们可能需要动态查看连接池中的一些指标,
// 来判断设置的值是否合理,或者检测连接池是否有异常情况出现
"TestReserved2Inner": 1, // TestReserved2Inner after
}
} #+end_src generate code [[./samples/gen_configoptions.go][samples/gen_configoptions.go]] #+begin_src go // Code generated by "gogen option"; DO NOT EDIT. // Exec: "gogen option" // Version: 0.0.1
package sample
import ( log "log" )
var _ = ConfigOptionDeclareWithDefault()
// Google Public DNS provides two distinct DoH APIs at these endpoints // Using the GET method can reduce latency, as it is cached more effectively. // RFC 8484 GET requests must have a ?dns= query parameter with a Base64Url encoded DNS message. The GET method is the only method supported for the JSON API. type ConfigOptions struct { // test comment 1 // test comment 2 TestNil interface{} // test comment 3 TestBool bool // test comment 4 // 这里是函数注释1 // 这里是函数注释2 TestInt int // default 32 TestInt64 int64 // int64 line TestSliceInt []int // slice int TestSliceInt64 []int64 // slice int64 line TestSliceString []string // slice string TestSliceBool []bool // slice bool line comment TestSliceIntNil []int // TestSliceIntNil line comment TestSliceByte []byte // TestSliceByte line comment // SliceInt Doc TestSliceIntEmpty []int TestMapIntInt map[int]int // TestMapIntInt line comment TestMapIntString map[int]string // TestMapIntString line comment TestMapStringInt map[string]int // TestMapStringInt line comment // MapStringString Doc TestMapStringString map[string]string // MapStringString Line Comment TestString string // Food Doc Food (*string) // Food Line Comment // Walk Doc Walk func() // Walk Line Comment // TestNilFunc TestNilFunc (func()) // 中文1 // TestReserved1_ TestReserved1 []byte // 在调优或者运行阶段,我们可能需要动态查看连接池中的一些指标, // 来判断设置的值是否合理,或者检测连接池是否有异常情况出现 TestReserved2 int // TestReserved2Inner after }
// test comment 1 // test comment 2 func WithTestNil(v interface{}) ConfigOption { return func(cc *ConfigOptions) ConfigOption { previous := cc.TestNil cc.TestNil = v return WithTestNil(previous) } } func WithTestBool(v bool) ConfigOption { return func(cc *ConfigOptions) ConfigOption { previous := cc.TestBool cc.TestBool = v return WithTestBool(previous) } }
// 这里是函数注释1 // 这里是函数注释2 func WithTestInt(v int) ConfigOption { return func(cc *ConfigOptions) ConfigOption { previous := cc.TestInt cc.TestInt = v return WithTestInt(previous) } } /// .. Omit part of the code
// SliceInt Doc func WithTestSliceIntEmpty(v ...int) ConfigOption { return func(cc *ConfigOptions) ConfigOption { previous := cc.TestSliceIntEmpty cc.TestSliceIntEmpty = v return WithTestSliceIntEmpty(previous...) } } func WithTestMapIntInt(v map[int]int) ConfigOption { return func(cc *ConfigOptions) ConfigOption { previous := cc.TestMapIntInt cc.TestMapIntInt = v return WithTestMapIntInt(previous) } }
/// .. Omit part of the code
// TestReserved1_ func withTestReserved1(v []byte) ConfigOption { return func(cc *ConfigOptions) ConfigOption { previous := cc.TestReserved1 cc.TestReserved1 = v return withTestReserved1(previous) } }
// 来判断设置的值是否合理,或者检测连接池是否有异常情况出现 func withTestReserved2(v int) ConfigOption { return func(cc *ConfigOptions) ConfigOption { previous := cc.TestReserved2 cc.TestReserved2 = v return withTestReserved2(previous) } }
// SetOption modify options func (cc *ConfigOptions) SetOption(opt ConfigOption) { _ = opt(cc) }
// ApplyOption modify options func (cc *ConfigOptions) ApplyOption(opts ...ConfigOption) { for _, opt := range opts { _ = opt(cc) } }
// GetSetOption modify and get last option func (cc *ConfigOptions) GetSetOption(opt ConfigOption) ConfigOption { return opt(cc) }
// ConfigOption option define type ConfigOption func(cc *ConfigOptions) ConfigOption
// NewConfigOptions create options instance. func NewConfigOptions(opts ...ConfigOption) *ConfigOptions { cc := newDefaultConfigOptions() for _, opt := range opts { _ = opt(cc) } if watchDogConfigOptions != nil { watchDogConfigOptions(cc) } return cc }
// InstallConfigOptionsWatchDog install watch dog func InstallConfigOptionsWatchDog(dog func(cc *ConfigOptions)) { watchDogConfigOptions = dog }
var watchDogConfigOptions func(cc *ConfigOptions)
// newDefaultConfigOptions new option with default value func newDefaultConfigOptions() *ConfigOptions { cc := &ConfigOptions{ TestNil: nil, TestBool: false, TestInt: 32, TestInt64: 32, TestSliceInt: []int{1, 2, 3}, TestSliceInt64: []int64{1, 2, 3}, TestSliceString: []string{"test1", "test2"}, TestSliceBool: []bool{false, true}, TestSliceIntNil: nil, TestSliceByte: nil, TestSliceIntEmpty: nil, TestMapIntInt: map[int]int{1: 1, 2: 2, 3: 3}, TestMapIntString: map[int]string{1: "test"}, TestMapStringInt: map[string]int{"test": 1}, TestMapStringString: map[string]string{"test": "test"}, TestString: "Meow", Food: nil, Walk: func() { log.Println("Walking") }, TestNilFunc: nil, TestReserved1: nil, TestReserved2: 1, } return cc }
#+end_src
** imake #+begin_example Flags: -h, --help help for imake --ignore-empty-struct ignore empty struct(not has funcions) --ignore-unexport-method is ignore unexport method (default true) --ignore-unexport-struct is ignore unexport struct (default true) -m, --match type match struct name;current option is mutually exclusive with type --mock generate struct mock functions -o, --output string output file name; default stdout -s, --suffix string add interface name suffix (default "IFace") --tags strings comma-separated list of build tags to apply --to string generated package name (default ".") -t, --type match list of type names; current option is mutually exclusive with match -v, --version version for imake #+end_example #+begin_src shell gogen imake "github.com/go-redis/redis/v8" --to redismock -m ".*Cmd$" -o samples/redismock/redis.go --mock #+end_src [[./samples/redismock/][redismock]] generate code sample
** TODO-LIST
[[https://github.com/ncw/gotemplate][github.com/ncw/gotemplate]]
** others
[[https://github.com/xyz347/pbidl/][pbidl - protobuf parse by goyacc]]