Hertz 源码解析—— hz new 是怎么生成代码文件的

591 阅读4分钟

前言

这是我参加 Cloudwego StudyGroup 第二期的第一篇文章,这次关于分析hz 代码生成工具的文章预计会连载至3期左右,主要原因为 hz 工具提供了自定义模板的功能。后续有时间也会介绍 Hertz 路由树之类的其他知识。

Hertz 是一个 Golang 微服务 HTTP 框架,在设计之初参考了其他开源框架 fasthttpginecho 的优势,并结合字节跳动内部的需求,使其具有高易用性、高性能、高扩展性等特点,目前在字节跳动内部已广泛使用。如今越来越多的微服务选择使用 Golang,如果对微服务性能有要求,又希望框架能够充分满足内部的可定制化需求,Hertz 会是一个不错的选择。

从 main.go 入手,由表及里

此为 Hertz 的主要目录结构, cmd/hz 此为这篇文章分析的重点,因为 Hertz 的核心代码大概不是我一篇文章就能说完的啦。

image-20220712003659744.png

我们先看看其中 go.mod 文件中所用到的第三方包,最为重要的包我已经写出了注释,自己写的时候也可以使用

image-20220712005248806.png

从先前的cmd/hz的文件结构不难看出,整个代码生成工具的入口就是main.go

image-20220712005927031.png 我标注的地方是后面我进行分析的入口,无疑干什么事都是要从头入手的,这里我们可以结合官方文档来进行分析, 从预留的注释来看 hz 工具是有插件和普通两种模式的,这里在官方文档中的介绍为两个部分。

image-20220712010943751.png

thrift.png

这也就解释了为什么 pluginMode() 中有判断 IDL 又有类型的选项了,因为 hz 同时支持 proto 和 thrift 两种 IDL 语言

进入 app.go, 分析命令行参数是如何进行初始化的

我们从 app.Init() 进入app.go 的 Init()方法, 下面为经过简化的源码,里面有相应的解释

很明显通过 init 后,工具就可以通过命令行接收指定参数了。后续的 commands 是通过组合选项来保证程序开源接收它所需的所有可能的参数。

看文章标题,大家其实就知道今天的主要目标就是搞清楚 new 这个命令到底干了些什么,我们可以接着往下看

carbon (1).png

这里是 New() 的主要逻辑,鉴于后续要大量使用 args, 我们先看看 Arguement 具体有什么参数。

other.png

其实这里已经写出了这个工具生成代码所需的所有参数,模式,生成文件的路径,IDL 语言的类型等,应有尽有。

大家都来看源码了,看点英文不要紧的。

other2.png

这里是 generateLayout() 的主要逻辑,先初始化 LayoutGenerator 和 Layout,再进行代码生成,再往下就是将 layout 的细化参数填入 generator 中,最后一同生成。可以进入 lg.GenerateByService(layout) 中继续查看

other4.png

因为是使用默认模板,所以这里直接就从 Layout 取出默认值来进行填充,下面的 generate 函数还会深入几次,我这里直接到最后的逻辑来解释渲染时什么时候发生的。

generator_code.png

这次只是大概的说明渲染时发生在这个时刻,但是我其实忽略了许多的细节,比如默认的配置在哪里?自定义配置了什么?也无需我会在下次的文章说明,但是如若我依旧没有提及,请自行寻找答案,因为我其实只是在阐明思路。

render.png

小结

这次源码分析大略的将代码生成的路线描述了一遍,这其中我刻意忽略了许多细节。因为文章只能起到一个思路指引的作用,而不可能面面俱到,细节是需要大家去深究的。

我希望我的文章的作用是可以让大家有信心看源码,养成通过学习源码来学习知识的习惯,进行自我驱动。只有学习是伴随人的一生的!

本文正在参加技术专题18期-聊聊Go语言框架