requestgen和callbackgen算是笔者在2021 年末开发的两个Go 程式语言开发的新武器,不过时间有限,本文就先只介绍requestgen。

requstgen 顾名思义就是request generator,帮助你一键刻完Request 程式码。

开发requestgen 的主要原因是最近几年在整合加密货币交易所的API,不断地在重复做API Client 开发的工作,但也因为Go 程式语言对于型别的要求相较Node.js 繁琐,也因此型别栏位都必须定义清楚,在程式码的撰写上势必得花更多功夫。

因此下定决心找时间利用Go 1.5 之后的go/ast, go/types 等Go 编译器的相关API 来开发了一个code generator。

不得不说,Go generate 真的是相当方便的一个工具,虽然Go 还没有泛型可以使用,但Go generate 是目前最接近这样性质的一个工具。

话不多说,先来看看Go generate 可以用来干嘛

一般来说,如果要开发一个API request 的衔接,通常都要先开发一个RESTful API Client 用来处理HTTP Request 请求,和HTTP Response 回应等等,如果要处理Authentication 那就相对麻烦。RESTful API Client 开发完之后,还要针对每一个API Endpoint 处理Request 的参数,有些使用GET 要带上Query parameters,有些则使用POST 同时带上Query parameters 和Body parameters,对于parameters 的处理,有些人使用相对弹性的map[string]interface{} ,但这样也没有办法很容易的对于栏位型别和栏位的值做验证,而写成struct 这类的data object,则要写更多getter, setter 的程式码来处理。

譬如:

req := client.NewPlaceOrderRequest() orderList, err := req.Symbol("BTCUSDT"). Price("3600"). Quantity("1.0"). OrderType("limit") Do(ctx)

要写出上面API 的背后的实作,少则百行,除了要写struct 栏位,还得加上setter, 以及最后处理参数验证与Request 发送的Do method。

但有了requestgen 之后,我们只需要描述Request 与Response 的结构即可。

首先是struct 的部分,要从API 文件上参考JSON ,然后改写成struct ,这个部分刚好GoLand 帮我们提供了一个工具可以在贴上JSON 的时候自动转成Go struct ,非常方便。

接着,只要在这个struct 上方加上一段//go:generate requestgen就可以自动产生对应的所有代码,少写相当多程式!

首先先把requestgen 需要的struct tag 加上:

上方可以看到param 这个struct tag,便是用来定义request 的parameter 名称。

而栏位的型别,只要是pointer 型别,对requestgen 来说就是可选栏位(optional parameter) 如果没有指定,就不会随着request 送出。

如果有验定栏位的值,则可以使用valid values 来定义,用“,” 来分隔数值。

如果是必要栏位,则可在param struct tag 加上required 这个option。

struct 的上方,可以看到一段go:generate 开头:

//go:generate requestgen -type PlaceOrderRequest

这就是告诉requestgen 要产生PlaceOrderRequest 这个struct type 的accessor methods。

上方是一个Minimal example,还没有完全满足我们的需求,我们的重点还是在于这个最难处理的Do(ctx) method。

因此在第二个范例,我们加上了更多requestgen 的参数,包含-method与-url用来指定这个API Request 调用的方法以及路径,最后还有回传的型别-responseType,请见下方范例:

其中,眼尖的读者可能发现了我们在struct 内的第一个栏位新增了一个requestgen.AuthenticatedAPIClient 这个栏位。

这个型别其实是一个interface,requestgen 在静态剖析你的struct 结构时,如果发现这个interface,他就会知道原来你要发送的API 是需要做Authentication 的API,会自动帮你呼叫实作AuthenticatedAPIClient 这个界面的NewAuthenticatedRequest 方法,它的原型如下:

只要你传递到Request struct 中的client 符合这个界面的需求,他就可以利用这个界面帮你介接你的API Request 以及API Response ,甚至API Response 的decoding (or unmarshaling)。

如此一来,requestgen 就会自动帮我们产生以下Do(ctx) 的实作:

可能有些读着觉得只是玩玩用的工具罢了,不,这可不是只是玩玩的工具,这个工具笔者已经正式用在BBGO 的交易所界面开发,是有真实的应用。