在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结构体的生成。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。