requestgen — Golang API Client 整合新利器

c9s
6 min readJan 2, 2022

--

requestgencallbackgen 算是筆者在 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 的交易所介面開發,是有真實的應用,有興趣的朋友可以看看 kucoin API 的整合實作

以及 requestgen 本身附上的範例:

如果有朋友有興趣甚至在使用後有些心得,也歡迎各位回饋意見。

最後一點無關的,如果還沒有 Kucoin 交易所帳號的朋友,也歡迎透過我下面的推薦連結註冊一下~

--

--