本文介绍 gengo 工具的 golang 代码生成技术,以及基于此完成的 golang annotation 插件。
代码生成的技术在各种语言中都很常用,尤其是静态语言,利用代码生成的技术可以实现一些大幅提高生产效率的工具。
比如 Java 中的 Annotation Lombok 会在Javac 解析成抽象语法树之后(AST), Lombok 根据自己的注解处理器,动态的修改 AST,增加新的节点(所谓代码),最终通过分析和生成字节码,根据具体的 Annotation 生成 Class 的 Getter、Setter 方法等,降低开发者的工作量。
广义上讲 C++ 的模版方法也是类似的代码生成技术,有时候使用生成代码技术不仅仅是出于降低工程量的角度,由于避免了运行时的自省调用,利用代码生成完成的功能往往执行效率也更好,比如 ffjson。
我们在另一篇文章中介绍的 protobuf 代码生成 也是一种常见的代码生成工具。利用 protoc 的生成工具,可以生成各种语言的代码,rpc server, client 模版代码,配合各种插件还能生成文档、脚本、Http 网关代码等。
gengo 是 kubernetes 项目中常用的代码生成工具,kubernetes 项目中大量使用了这个工具用于代码生成。 gengo 更多的设计为一个比较通用的代码生成工具,完成代码表达树解析,生成的工作。
code-generator 是对 gengo 的一层包装,完成 kubernetes 中常见的一些代码生成任务,比如 客户端代码生成、deepcopy 类代码生成等等,大部分是围绕 kubernetes api 对象的生成工具。
工具 | 作用 |
---|---|
client-gen | 为 API 资源创建 typed clientsets 即 rest client |
conversion-gen | 用于为 API 资源 生成 |
deepcopy-gen | 为 API 资源 T 生成 DeepCopy\DeepCopyInto 等函数代码 |
defaulter-gen | API 资源的 default 函数还是要手写的,这个工具会帮助 注册哦 default 函数,用于自动执行 default 函数 |
informer-gen | 为API 资源创建 informers,它会基于接口提供 event 事件来对服务器上的自定义资源的任何改动做出反应 |
lister-gen | 为API 资源 创建 listers 函数,会提供一个只读的缓存层来相应GET和LIST请求 |
openapi-gen | 为API资源创建 openapi 定义文档 |
set-gen | 为 builtin 类型创建对应的 sets 类,即 hash set 类型,由于 go不支持泛型,利用这个工具自动生成代码 |
Gengo 的目标是完成一个方便用户自行实现各种代码生成工具的库,他完成了几项工作
实际实现的插件要实现这个 interface
var (...)
const xxx
func init(){}
import (name "path/to/pkg")
(c *Context) ExecutePackage(outDir string, p Package)
函数,会依次执行 generator interface里面的方法使用过 Java 开发项目的同学一定对 java 中的 annotation 系统印象深刻,让我们来看一段代码。
@Getter
@Setter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class SomeEntity implements Serializable {
@CreatedBy
@Column(name = "create_by", updatable = false)
@ApiModelProperty(value = "创建人", hidden = true)
private String createBy;
@CreationTimestamp
@Column(name = "create_time", updatable = false)
@ApiModelProperty(value = "创建时间", hidden = true)
private Timestamp createTime;
}
这段代码中 Annotation 的行数甚至超过的 实际的Java 代码,利用 Annotation 的强大,Java 开发中可以省略大量的重复代码,各种高级库和框架利用 annotation 完成了大量的自动化工作。Spring 框架中的核心 面向切面AOP
、IOC控制反转
都是基于 Annotation 实现的。
由于类似的概念实在是太好用了,在 go 语言中,很多先行者也做了一些尝试,比如针对 IOC 的 facebook inject、uber dig、google wire 、go-spring, 其中 inject、 dig 和 go-spring 都是基于 reflect 的,受制于 golang 的反射能力,代码中并不能做到像 Java 中那么智能,注入之前还是需要先手动提供一些构建方法,不是那么方便,wire 基于代码生成,风格和 Java 中差别比较大。
那么我们能不能利用 gengo 实现一套 annotation 系统,实现类似 Java 中的注解功能呢,如果实现了这个,那么 用它来实现 IOC 只是其中的一个用例插件。
实战代码在 go-annotation
对照 Java 的 Annotation 系统,一个 Annotation 比较关注的两个点:
使用 Annotation@Annotation名字=AnnotationBody
表示使用一个具体的 annotation, Annotation 是一个固定前缀,可以作为工具的输入参数修改,@
后为 Annotation的名字,为一个具体的 Annotation类型,AnnotationBody 是注解的具体内容,为了简化设计,我们定义 AnnotationBody 为 JSON 格式,具体的注解内容会被当成 JSON 文本,再具体 解析到一个 Annotation 类型中去。
Template() string
函数完成,如果某个注解 实现了 Template() string
函数,表示这种注解插件同时需要生成一些自定义的代码。Component 插件实现类似 Java 中的依赖注入能力。比如下面的 定义。
// Annotation@Component
type ComponentA struct {
B1 *ComponentB `autowired:"true"` // Will populate with new(ComponentB)
B2 *ComponentB `autowired:"true"` // Will populate with new(ComponentB)
B3 *ComponentB
}
// Annotation@Component={"type": "Singleton"}
type ComponentB struct {
C *ComponentC `autowired:"true"` // Will populate with NewComponentC()
}
// Annotation@Component
type ComponentC struct {
D *ComponentD `autowired:"true"` // Will populate with NewComponentD()
IntValue int
}
func NewComponentC() *ComponentC {
return &ComponentC{IntValue: 1}
}
// Annotation@Component
type ComponentD struct {
IntValue int
}
func NewComponentD() (*ComponentD, error) {
return &ComponentD{IntValue: 2}, nil
}
我们希望 创建 ComponentA 的时候
Singleton
类型,因此我们希望 B1字段 和 B2字段应该一样,也就是说 ComponentB 的实例只会创建一个。autowired
的,我们希望自动识别出 NewComponentD 函数为 Constructor 函数,然后自动创建 ComponentD例如, 用 Annotation 系统实现的内置插件 Component, 实现了类似 Java 中的依赖注入功能, 具体使用请参考 examples/example_test.go
差不多了,这基本上是一个可以使用的 并且实现了 内置 IOC 插件的 Annotation 系统了,当然这才是个开始,很多好用的插件还可以继续实现。
欢迎关注这个项目的进展 go-annotation。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有