#關於Swaggo
相信很多程式猿和我一樣不喜歡寫API文件。寫程式碼多舒服,寫文件不僅要花費大量的時間,有時候還不能做到面面具全。但API文件是必不可少的,相信其重要性就不用我說了,一份含糊的文件甚至能讓前後端人員打起來。 而今天這篇部落格介紹的swaggo就是讓你只需要專注於程式碼就可以生成完美API文件的工具。廢話說的有點多,我們直接看文章。
或許你使用過Swagger, 而 swaggo就是代替了你手動編寫yaml的部分。只要通過一個命令就可以將註釋轉換成文件,這讓我們可以更加專注於程式碼。
目前swaggo主要實現了swagger 2.0 的以下部分功能:
基本結構(Basic Structure)
API 地址與基本路徑(API Host and Base Path)
路徑與操作 (Paths and Operations)
引數描述(Describing Parameters)
請求引數描述(Describing Request Body)
返回描述(Describing Responses)
MIME 型別(MIME Types)
認證(Authentication)
Basic Authentication
API Keys
新增例項(Adding Examples)
檔案上傳(File Upload)
列舉(Enums)
按標籤分組(Grouping Operations With Tags)
擴充套件(Swagger Extensions)
下文內容均以gin-swaggo為例
2020/05/16 更新:
swag 升級到了 v1.6.5,返回資料格式有更新。
最新的請關注官網文件。
本文最後,優化部分可以瞭解一下。
#使用使用
#安裝swag-cli-及下載相關包安裝swag cli
及下載相關包
要使用swaggo,首先需要安裝swag cli
。
go get -u github.com/swaggo/swag/cmd/swag
然後我們還需要兩個包。
# gin-swagger 中介軟體
go get github.com/swaggo/gin-swagger
# swagger 內建檔案
go get github.com/swaggo/gin-swagger/swaggerFiles
可以看一下自己安裝的版本
swag --version
swag version v1.6.5
#在main-go內添加註釋在main.go
內添加註釋
package main
import (
"github.com/gin-gonic/gin"
ginSwagger "github.com/swaggo/gin-swagger"
"github.com/swaggo/gin-swagger/swaggerFiles"
)
// @title Swagger Example API
// @version 1.0
// @description This is a sample server celler server.
// @termsOfService https://razeen.me
// @contact.name Razeen
// @contact.url https://razeen.me
// @contact.email [email protected]
// @license.name Apache 2.0
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html
// @host 127.0.0.1:8080
// @BasePath /api/v1
funcmain() {
r := gin.Default()
store := sessions.NewCookieStore([]byte("secret"))
r.Use(sessions.Sessions("mysession", store))
r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
v1 := r.Group("/api/v1")
{
v1.GET("/hello", HandleHello)
v1.POST("/login", HandleLogin)
v1Auth := r.Use(HandleAuth)
{
v1Auth.POST("/upload", HandleUpload)
v1Auth.GET("/list", HandleList)
}
}
r.Run(":8080")
}
如上所示,我們需要匯入
ginSwagger "github.com/swaggo/gin-swagger"
"github.com/swaggo/gin-swagger/swaggerFiles"
同時,添加註釋。其中:
titile
: 文件標題version
: 版本description,termsOfService,contact ...
這些都是一些宣告,可不寫。license.name
額,這個是必須的。host
,BasePath
: 如果你想直接swagger除錯API,這兩項需要填寫正確。前者為服務文件的埠,ip。後者為基礎路徑,像我這裡就是“/api/v1”。- 在原文件中還有
securityDefinitions.basic
,securityDefinitions.apikey
等,這些都是用來做認證的,我這裡暫不展開。
到這裡,我們在mian.go
同目錄下執行swag init
就可以自動生成文件,如下:
➜ swaggo-gin git:(master) ✗ swag init
2019/01/12 21:29:14 Generate swagger docs....
2019/01/12 21:29:14 Generate general API Info
2019/01/12 21:29:14 create docs.go at docs/docs.go
然後我們匯入這個自動生成的docs
包,執行:
package main
import (
"github.com/gin-gonic/gin"
ginSwagger "github.com/swaggo/gin-swagger"
"github.com/swaggo/gin-swagger/swaggerFiles"
_ "github.com/razeencheng/demo-go/swaggo-gin/docs"
)
// @title Swagger Example API
// @version 1.0
// ...
➜ swaggo-gin git:(master) ✗ go build
➜ swaggo-gin git:(master) ✗ ./swaggo-gin
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
[GIN-debug] [WARNING] Running in"debug" mode. Switch to "release" mode in production.
- using env: export GIN_MODE=release
- using code: gin.SetMode(gin.ReleaseMode)
[GIN-debug] GET /api/v1/hello --> main.HandleHello (3 handlers)
[GIN-debug] POST /api/v1/login --> main.HandleLogin (3 handlers)
[GIN-debug] POST /upload --> main.HandleUpload (4 handlers)
[GIN-debug] GET /list --> main.HandleList (4 handlers)
[GIN-debug] GET /swagger/*any --> github.com/swaggo/gin-swagger.WrapHandler.func1 (4 handlers)
[GIN-debug] Listening and serving HTTP on :8080
瀏覽器開啟http://127.0.0.1:8080/swagger/index.html, 我們可以看到如下文件標題已經生成。
#在Handle函式上添加註釋在Handle函式上添加註釋
接下來,我們需要在每個路由處理函式上加上註釋,如:
// @Summary 測試SayHello
// @Description 向你說Hello
// @Tags 測試
// @Accept mpfd
// @Produce json
// @Param who query string true "人名"
// @Success 200 {string} string "{"msg": "hello Razeen"}"
// @Failure 400 {string} string "{"msg": "who are you"}"
// @Router /hello [get]
funcHandleHello(c *gin.Context) {
who := c.Query("who")
if who == "" {
c.JSON(http.StatusBadRequest, gin.H{"msg": "who are u?"})
return
}
c.JSON(http.StatusOK, gin.H{"msg": "hello " + who})
}
我們再次swag init
, 執行一下。
此時,該API的相關描述已經生成了,我們點選Try it out
還可以直接測試該API。
是不是很好用,當然這並沒有結束,這些註釋欄位,我們一個個解釋。
這些註釋對應出現在API文件的位置,我在上圖中已經標出,這裡我們主要詳細說說下面引數:
#TagsTags
Tags 是用來給API分組的。
#AcceptAccept
接收的引數型別,支援表單(mpfd
) , JSON(json
)等,更多如下表。
#ProduceProduce
返回的資料結構,一般都是json
, 其他支援如下表:
Mime Type宣告application/jsonjsontext/xmlxmltext/plainplainhtmlhtmlmultipart/form-datampfdapplication/x-www-form-urlencodedx-www-form-urlencodedapplication/vnd.api+jsonjson-apiapplication/x-json-streamjson-streamapplication/octet-streamoctet-streamimage/pngpngimage/jpegjpegimage/gifgif
#ParamParam
引數,從前往後分別是:
@Param who query string true “人名”
@Param
1.引數名``2.引數型別``3.引數資料型別``4.是否必須``5.引數描述``6.其他屬性
1.引數名
引數名就是我們解釋引數的名字。
2.引數型別
引數型別主要有四種:
path
該型別引數直接拼接在URL中,如Demo中HandleGetFile
:
// @Param id path integer true "檔案ID"
```
-
`query` 該型別引數一般是組合在URL中的,如[Demo](https://github.com/razeencheng/demo-go/blob/master/swaggo-gin/handle.go)中`HandleHello`
```golang
// @Param who query string true "人名"
```
`formData` 該型別引數一般是`POST,PUT`方法所用,如[Demo](https://github.com/razeencheng/demo-go/blob/master/swaggo-gin/handle.go)中`HandleLogin`
```golang
// @Param user formData string true "使用者名稱" default(admin)
```
`body` 當`Accept`是`JSON`格式時,我們使用該欄位指定接收的JSON型別
```golang
// @Param param body main.JSONParams true "需要上傳的JSON"
```
3.引數資料型別
資料型別主要支援一下幾種:
- string (string)
- integer (int, uint, uint32, uint64)
- number (float32)
- boolean (bool)
注意,如果你是上傳檔案可以使用`file`, 但引數型別一定是`formData`, 如下:
```golang
// @Param file formData file true "檔案"
```
4.是否是必須
表明該引數是否是必須需要的,必須的在文件中會黑體標出,測試時必須填寫。
5.引數描述
就是引數的一些說明
6.其他屬性
除了上面這些屬性外,我們還可以為該引數填寫一些額外的屬性,如列舉,預設值,值範圍等。如下:
```golang
列舉
// @Param enumstring query string false "string enums" Enums(A, B, C)
// @Param enumint query int false "int enums" Enums(1, 2, 3)
// @Param enumnumber query number false "int enums" Enums(1.1, 1.2, 1.3)
值新增範圍
// @Param string query string false "string valid" minlength(5) maxlength(10)
// @Param int query int false "int valid" mininum(1) maxinum(10)
設定預設值
// @Param default query string false "string default" default(A)
而且這些引數是可以組合使用的,如:
// @Param enumstring query string false "string enums" Enums(A, B, C) default(A)
```
##### [#Success](#Success)Success
指定成功響應的資料。格式為:
> // @Success `1.HTTP響應碼``{2.響應引數型別}``3.響應資料型別``4.其他描述`
1.HTTP響應碼
也就是200,400,500那些。
2.響應引數型別 / 3.響應資料型別
返回的資料型別,可以是自定義型別,可以是json。
- 自定義型別
在平常的使用中,我都會返回一些指定的模型序列化JSON的資料,這時,就可以這麼
```golang
// @Success 200 {object} main.File
```
其中,模型直接用`包名.模型`即可。你會說,假如我返回模型陣列怎麼辦?這時你可以這麼寫:
```golang
// @Success 200 {anrry} main.File
```
將如你只是返回其他的資料格式可如下寫:
```golang
// @Success 200 {string} string ""
4.其他描述
可以新增一些說明。
#FailureFailure
同Success。
#RouterRouter
指定路由與HTTP方法。格式為:
// @Router
/path/to/handle
[HTTP方法
]
不用加基礎路徑哦。
#生成文件與測試生成文件與測試
其實上面已經穿插的介紹了。
在main.go
下執行swag init
即可生成和更新文件。
點選文件中的Try it out
即可測試。 如果部分API需要登陸,可以Try登陸介面即可。
#優化優化
看到這裡,基本可以使用了。但文件一般只是我們測試的時候需要,當我的產品上線後,介面文件是不應該給使用者的,而且帶有介面文件的包也會大很多(swaggo是直接build到二進位制裡的)。
想要處理這種情況,我們可以在編譯的時候優化一下,如利用build tag
來控制是否編譯文件。
在main.go
宣告swagHandler
,並在該引數不為空時才加入路由:
package main
//...
var swagHandler gin.HandlerFunc
funcmain(){
// ...
if swagHandler != nil {
r.GET("/swagger/*any", swagHandler)
}
//...
}
同時,我們將該引數在另外加了build tag
的包中初始化。
// +build doc
package main
import (
_ "github.com/razeencheng/demo-go/swaggo-gin/docs"
ginSwagger "github.com/swaggo/gin-swagger"
"github.com/swaggo/gin-swagger/swaggerFiles"
)
funcinit() {
swagHandler = ginSwagger.WrapHandler(swaggerFiles.Handler)
}
```
之後我們就可以使用`go build -tags "doc"`來打包帶文件的包,直接`go build`來打包不帶文件的包。
你會發現,即使我這麼小的Demo,編譯後的大小也要相差19M !
```shell
➜ swaggo-gin git:(master) ✗ go build
➜ swaggo-gin git:(master) ✗ ll swaggo-gin
-rwxr-xr-x 1 xxx staff 15M Jan 13 00:23 swaggo-gin
➜ swaggo-gin git:(master) ✗ go build -tags "doc"
➜ swaggo-gin git:(master) ✗ ll swaggo-gin
-rwxr-xr-x 1 xxx staff 34M Jan 13 00:24 swaggo-gin
文章到這裡也就結束了,完整的Demo地址在這裡。
本文章摘自https://razeencheng.com/post/go-swagger.html