在 Golang 开发中,我们经常会设计各种各样的结构体,然后给各个字段添加各种各样的标签。
例如,使用 json:something
来做 JSON 的序列化和反序列化
package x
type T struct{
MyField string `json:"my_field"`
}
众所周知,命名是编程中的两大难事之一,当我们有了这些标签之后,我们会面临额外的一些问题如下:
camelCase
还是 蛇形法 snake_case
?camelCase
,对于像 UserID
这样的,应该使用 userId
还是 userID
?虽然我们可以在 Lint 阶段或者自动化测试里面去检测这些问题,但是我会更偏向于下面的做法:
永远不要通过人工来管理这些标签,而是通过工具化去自动化地生成。
你可以使用 Gozz
来很轻易地实现这个模式:
下面有个很简单的例子,我们想要填充 json
和 bson
两种标签给我们的结构体
package tag01
// +zz:tag:json,bson:{{ snake .FieldName }}
type User struct {
Id string
Name string
Address string
CreatedAt time.Time
UpdatedAt time.Time
}
只需要在结构体上面加上一个注解 +zz:tag:json,bson:{{ snake .FieldName}}
然后执行 gozz run -p "tag" ./
你会发现这些问题就会彻底得到解决,代码的标签会被自动化按模版格式填充:
package tag01
// +zz:tag:json,bson:{{ snake .FieldName }}
type User struct {
Id string `bson:"id" json:"id"`
Name string `bson:"name" json:"name"`
Address string `bson:"address" json:"address"`
CreatedAt time.Time `bson:"created_at" json:"created_at"`
UpdatedAt time.Time `bson:"updated_at" json:"updated_at"`
}
最后 只需要将这些命令放到项目的 Makefile 在进行构建流水线时自动化执行,或者加到 commit hooks
里,这些结构体标签的规范从此以后都不需要人工介入。
上面的例子展示了 gozz-tag
的一些基本功能,下面的例子会额外展示这个工具的一些强大特性:
key
使用了不同的模版格式,以及 golang 的模版函数方法// +zz:tag:json,bson:{{ snake .FieldName }}
type (
User struct {
Id string
Name string
Address string
CreatedAt time.Time
UpdatedAt time.Time
}
// +zz:tag:json,bson:{{ camel .FieldName }}
Book struct {
Id string
Title string
CreatedAt time.Time
UpdatedAt time.Time
}
Order struct {
Id string
UserId string
BookId string
// +zz:tag:json,bson:{{ upper .FieldName | upper }}
CreatedAt time.Time
// +zz:tag:+json:,omitempty
UpdatedAt time.Time
}
)
执行 gozz
命令之后 ,文件会被更新为
// +zz:tag:json,bson:{{ snake .FieldName }}
type (
User struct {
Id string `bson:"id" json:"id"`
Name string `bson:"name" json:"name"`
Address string `bson:"address" json:"address"`
CreatedAt time.Time `bson:"created_at" json:"created_at"`
UpdatedAt time.Time `bson:"updated_at" json:"updated_at"`
}
// +zz:tag:json,bson:{{ camel .FieldName }}
Book struct {
Id string `bson:"id" json:"id"`
Title string `bson:"title" json:"title"`
CreatedAt time.Time `bson:"createdAt" json:"createdAt"`
UpdatedAt time.Time `bson:"updatedAt" json:"updatedAt"`
}
Order struct {
Id string `bson:"id" json:"id"`
UserId string `bson:"user_id" json:"user_id"`
BookId string `bson:"book_id" json:"book_id"`
// +zz:tag:json,bson:{{ snake .FieldName | upper }}
CreatedAt time.Time `bson:"CREATED_AT" json:"CREATED_AT"`
// +zz:tag:+json:,omitempty
UpdatedAt time.Time `bson:"updated_at" json:"updated_at,omitempty"`
}
)
需求都被完美解决了。
所以,相信在 Gozz
的帮助下,我们已经不需要去人工地维护这些结构体的标签规范了,只需要把注解加在定义块上,然后把生成的命令放到开发流水线中。
实际上,这个功能只是 Gozz
其中一个内置插件,它还提供了很多其他强大的插件,可以帮我们借助注解去做很多更强大的事情,比如 自动化的依赖注入、API 路由的自动生成 还有 ORM 结构体的生成。