缘起
写代码里有个绕不开的话题就是如何写构造函数
- Java 里有 JavaBean 作为标准,空构造参数 + 自定义的 setter
- C++ 里靠重载实现任意场景的构造
- Python 里可以可以支持传你需要的参数
Go 呢,一无所有,最通行的办法,大概是可变参作为可选的 options
func NewX(options ...Option) *X {
x := &X{}
for _, opt := range options {
opt.apply(x)
}
return x
}
但是,你每次不得不把一个个简单的参数定义成一大堆的 option,多么烦人。
所以,goption 就出场了
一睹为快
是不是太快了看不清。听我慢慢道来。
以 Goland 为示例,首先在定义 struct 时添加标识
//go:generate goption -p . -c Person -w
type Person struct{
// your person fields
}
这样的好处是,IDE 可以为你提供快捷按钮,你只需要点一下就生成了。
点击按钮后,会在同 packagge 下生成 person_option_gen.go
代码大约是这个样子:
type PersonOption func(*Person)
func NewPerson(opts ...PersonOption) (person *Person) {
person = &Person{}
for _, opt := range opts {
opt(person)
}
return
}
func WithPersonName(name string) func(*Person) {
return func(person *Person) {
person.Name = name
}
}
// ...
如何使用呢,也很简单:
func main() {
p1 := NewPerson() // 普通构造方式
p2 := NewPerson( // 自定义字段方式
WithPersonName(`zhangsan`),
WithPersonAge(18),
)
println(p1, p2)
}
使用起来真是爽了不少。
放上代码地址:https://github.com/micln/goption
如何实现
最开始绕了点弯路,自己一层层解析 ast.Node,后来发现 go/doc 已经帮你解析了 package,里面有哪些 Types,哪些 Funcs,都非常清楚,可以直接拿来用。
唯一需要处理的就是如何 ast.Expr 表示的代码展示出来,好在之前玩过 ast 相关的,也整理了一下 astutil 放了出来,后面还会继续完善。所以就大大减少了难度。
后续
费这么大劲如果只做这一件事确实有点亏,后续希望把 Generator 开放出来,我帮你解析源码和集成 IDE,你只需要自定义模板,就可以生成任何你想要的辅助方法。