簡(jiǎn)介
對(duì)于 API 服務(wù)來(lái)說(shuō), 文檔是必不可少的.
然而文檔卻挺煩人的, 尤其是同步更新的問(wèn)題. 如果選擇手寫(xiě)文檔, 經(jīng)常會(huì)忘了更新文檔;
或者處于高速開(kāi)發(fā)的前期, 來(lái)不及更新文檔.
現(xiàn)在更推崇的方式是文檔即注釋, 就是將文檔作為注釋, 和代碼同步更新,
使用自動(dòng)生成文檔的方式實(shí)時(shí)更新.
另一種概念是文檔即測(cè)試, 讓文檔不但能看, 也能用, 這對(duì)于 API 文檔來(lái)說(shuō),
是一個(gè)巨大的便利. 有了它, 再也不用一邊看文檔, 一邊開(kāi)著 Postman 實(shí)驗(yàn)了.
這就是 swagger.
swagger 起步
swagger 提供了很多工具用于創(chuàng)建 API 文檔, 尤其是創(chuàng)建了 RESTful APIs 標(biāo)準(zhǔn).
這個(gè) RESTful APIs 標(biāo)準(zhǔn)又稱為 OpenAPI Specification, 目前有兩個(gè)規(guī)范,
2.0 和 3.0. 大部分的實(shí)現(xiàn)都是基于 2.0 的.
這個(gè)項(xiàng)目使用的也是 2.0 規(guī)范.
安裝 swag 工具, 也可以直接下載預(yù)編譯的二進(jìn)制文件.
go get -u github.com/swaggo/swag/cmd/swag
在項(xiàng)目根目錄下運(yùn)行 swag init, 應(yīng)該會(huì)創(chuàng)建 docs 目錄.
swag init
安裝 swag-gin.
go get -u github.com/swaggo/gin-swagger
go get -u github.com/swaggo/files
到這里, 依賴已經(jīng)安裝完成了, 剩下的就是編寫(xiě)文檔了.
編寫(xiě)文檔
畢竟是一種規(guī)范, 還是要學(xué)習(xí)它的使用方式的, 如果有興趣, 可以看
原始的規(guī)范.
這里看 swag 庫(kù)的文檔就行了,
Declarative Comments Format.
使用的是聲明式的符號(hào)記法, 主要格式是 @key value, 即鍵值對(duì),
最后解析后生成的其實(shí)是一整個(gè) json 文件.
編寫(xiě) main 函數(shù)的注釋, 定義了 API 的通用信息.
// @title Apiserver API
// @version 1.0
// @description This is a simple api server.
// @contact.name coolcat
// @contact.url http://coolcat.io/support
// @contact.email help@coolcat.io
// @license.name Apache 2.0
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html
// @host 127.0.0.1:8081
// @BasePath /v1
// @securityDefinitions.apikey ApiKeyAuth
// @in header
// @name Authorization
func main() {
cmd.Execute()
}
在上面的注釋里, 主要有四部分, 分別定義了:
- 標(biāo)題, 版本號(hào), 描述
- 聯(lián)系信息
- license
- 安全定義
更新 router.go, 將 swagger 和 gin 結(jié)合:
import {
swaggerFiles "github.com/swaggo/files"
ginSwagger "github.com/swaggo/gin-swagger"
// docs is generated by Swag CLI, you have to import it.
_ "tzh.com/web/docs"
}
func Load(g *gin.Engine, mw ...gin.HandlerFunc) *gin.Engine {
...
// swagger 文檔
// The url pointing to API definition
// /swagger/index.html
url := ginSwagger.URL("/swagger/doc.json")
g.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler, url))
...
}
剩下的就是編寫(xiě)每個(gè)接口的文檔了, 舉個(gè)例子, login 接口的文檔如下:
// @Summary 登錄
// @Description 登錄賬戶, 獲取 token
// @Tags login
// @Accept json
// @Produce json
// @Param body body model.UserModel true "User login""
// @Success 200 {object} model.Token "{"code":0,"message":"OK","data":{"token":"name"}}"
// @Router /login [post]
func Login(ctx *gin.Context) {
這里定義了接口的基本屬性, 包括路徑, 請(qǐng)求類型, 成功時(shí)的輸出, 輸出格式等.
// @Summary 獲取用戶
// @Description 從數(shù)據(jù)庫(kù)中獲取用戶信息
// @Tags user
// @Accept json
// @Produce json
// @Security ApiKeyAuth
// @Param id path uint64 true "user id in database"
// @Success 200 {object} model.UserModel "{"code":0,"message":"OK","data": {}}"
// @Router /user/{id} [get]
func Get(ctx *gin.Context) {
get 接口比上面的 login 接口多了一個(gè)參數(shù) @Security ApiKeyAuth, 用于定義認(rèn)證方式.
已經(jīng)在 main 函數(shù)的注釋中定義了認(rèn)證方式 ApiKeyAuth 了, 這里就可以直接指定了.
每次更新完文檔之后, 都需要運(yùn)行 swag init 更新 docs 目錄.
啟動(dòng)服務(wù)器之后, 就可以在 /swagger/index.html 上訪問(wèn) API 文檔了.
更多的文檔注釋, 可以在源代碼中查看.
運(yùn)行
文檔編寫(xiě)完成之后, 都需要運(yùn)行 swag init 更新, 可以將這個(gè)步驟定義在 Makefile 文件中.
build: updoc
go build -ldflags ${ldflags} ./
run: updoc
go run -ldflags ${ldflags} ./
docker: updoc
go run -ldflags ${ldflags} ./ -c ./conf/config_docker.yaml
updoc:
go mod download
go get -u github.com/swaggo/swag/cmd/swag
swag init
運(yùn)行 make run, 然后就可以在瀏覽器中打開(kāi) http://localhost:8081/swagger/index.html 并查看文檔了.
打開(kāi) http://localhost:8081/swagger/doc.json 可以查看生成的 json 文件,
使用這個(gè) json 文件, 可以在其他的 swagger gui 中查看 API 文檔.

總結(jié)
swagger 為文檔的編寫(xiě)提供了極大的便利, 工具雖好, 更重要的是堅(jiān)持.
當(dāng)前部分的代碼
作為版本 v0.16.0