Go 使用原生 Swagger

Golang use swagger

Swagger 是一个规范且完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。

当通过 Swagger 进行正确定义,用户可以理解远程服务并使用最少实现逻辑与远程服务进行交互。

支持 API 自动生成同步的在线文档。使用 Swagger 后可以直接通过代码生成文档,不再需要自己手动编写接口文档了,对程序员来说非常友好,可以节约写文档的时间。

提供 Web 页面在线测试 API。光有文档还不够,Swagger 生成的文档还支持在线测试。参数和格式都定好了,直接在界面上输入参数对应的值即可在线测试接口。

Swag 能将 Go 的注释转换为 Swagger 文档。

1
2
3
4
# 安装swag
go get github.com/swaggo/swag/cmd/swag
# 查看版本
swag -v

https://cdn.xiaobinqt.cn/xiaobinqt.io/20220519/90cbf963f17a451187e3527877bd8172.png?imageView2/0/q/75|watermark/2/text/eGlhb2JpbnF0/font/dmlqYXlh/fontsize/1000/fill/IzVDNUI1Qg==/dissolve/52/gravity/SouthEast/dx/15/dy/15
swag cli

swagger-ui 库下载 dist 文件夹到自己的项目中,并更名为 swagger(更名不是必须的)。

把 swagger 中的 swagger-initializer.js 文件中有个 url 参数,全局替换 swagger 文件夹中的这个 url 参数值为 ./swagger.json

https://cdn.xiaobinqt.cn/xiaobinqt.io/20220519/28a4221079dd478e926209292027748b.png?imageView2/0/q/75|watermark/2/text/eGlhb2JpbnF0/font/dmlqYXlh/fontsize/1000/fill/IzVDNUI1Qg==/dissolve/52/gravity/SouthEast/dx/15/dy/15
swagger-initializer.js url

https://cdn.xiaobinqt.cn/xiaobinqt.io/20220519/1fd26413ebe2426e8263e8cd7182526a.png?imageView2/0/q/75|watermark/2/text/eGlhb2JpbnF0/font/dmlqYXlh/fontsize/1000/fill/IzVDNUI1Qg==/dissolve/52/gravity/SouthEast/dx/15/dy/15
替换所有

swagger 是以注释的方式描述的,然后使用 swag cli 生成的文档。

比如我有一个 main.go 文件,文件内容如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package main

import (
	"embed"
	"net/http"

	"github.com/go-martini/martini"
)

//go:embed swagger
var embededFiles embed.FS

// @title 测试 API
// @version 4.0
// @description 测试 API V4.0
// @securityDefinitions.apiKey MyApiKey
// @in header
// @name Xiaobinqt-Api-Key
// @BasePath /
func main() {
	m := martini.Classic()
	m.Get("/swagger/**", http.FileServer(http.FS(embededFiles)).ServeHTTP)
	m.Post("/api/login", Login)
	m.Run()
}

type Req struct {
	Email    string `json:"email"` // 邮箱
	Password string `json:"password"`
}

// @Tags 用户管理
// @Summary 用户登录
// @Security MyApiKey
// @accept application/json
// @Produce application/json
// @Param data body Req true "email: 用户名,password: 密码"
// @Success 200 {object} EdgeInstanceList
// @Router /api/login [POST]
func Login(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("hello"))
}

type EdgeInstanceList struct {
	A string
	B string
}

使用 swag cli 生成 swagger 文档:

https://cdn.xiaobinqt.cn/xiaobinqt.io/20220519/41886c08ae484deaa904bec886cfa532.png?imageView2/0/q/75|watermark/2/text/eGlhb2JpbnF0/font/dmlqYXlh/fontsize/1000/fill/IzVDNUI1Qg==/dissolve/52/gravity/SouthEast/dx/15/dy/15
生成 swagger 文档

访问 swagger 路由:

https://cdn.xiaobinqt.cn/xiaobinqt.io/20220519/5bdd5117ff644d37a9a895c781a6b5b0.png?imageView2/0/q/75|watermark/2/text/eGlhb2JpbnF0/font/dmlqYXlh/fontsize/1000/fill/IzVDNUI1Qg==/dissolve/52/gravity/SouthEast/dx/15/dy/15
访问 swagger 路由

有的 api 需要加上 header 头信息才能正确访问,这时可以添加注释信息:

1
2
3
// @securityDefinitions.apiKey MyApiKey
// @in header
// @name Xiaobinqt-Api-Key

@in header 设置,在请求 header 中,@name Xiaobinqt-Api-Key header 字段为Xiaobinqt-Api-Key@securityDefinitions.apiKey 固定写法,MyApiKey在每个方法中的@Security注释信息值,如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// @Tags 用户管理
// @Summary 用户登录
// @Security MyApiKey
// @accept application/json
// @Produce application/json
// @Param data body Req true "email: 用户名,password: 密码"
// @Success 200 {object} EdgeInstanceList
// @Router /api/login [POST]
func Login(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("hello"))
}

如果在 swagger 页面 Available authorizations 的值不为空,那么每次请求都会带着Xiaobinqt-Api-Key这个 header 头,值就是Available authorizations 填入的值。

https://cdn.xiaobinqt.cn/xiaobinqt.io/20220519/17586935d9494b30b83b30be0e46f45a.png?imageView2/0/q/75|watermark/2/text/eGlhb2JpbnF0/font/dmlqYXlh/fontsize/1000/fill/IzVDNUI1Qg==/dissolve/52/gravity/SouthEast/dx/15/dy/15
Available authorizations

https://cdn.xiaobinqt.cn/xiaobinqt.io/20220519/125010439aed41258b007ab94bba2309.png?imageView2/0/q/75|watermark/2/text/eGlhb2JpbnF0/font/dmlqYXlh/fontsize/1000/fill/IzVDNUI1Qg==/dissolve/52/gravity/SouthEast/dx/15/dy/15
Execute

具体可以参看:https://swagger.io/docs/specification/describing-parameters/

  • body
1
2
3
4
5
6
7

type Req struct {
	Email    string `json:"email"` // 邮箱
	Password string `json:"password"`
}

// @Param data body Req true "email: 用户名,password: 密码"
  • path
1
// @Param  user_id path string true "用户ID"
  • query
1
// @Param  search query string false "搜索内容"

完整注释如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// @Tags 用户管理
// @Summary 用户登录
// @Security MyApiKey
// @accept application/json
// @Produce application/json
// @Param  user_id path string true "用户ID"
// @Param  search query string false "搜索内容"
// @Param data body Req true "email: 用户名,password: 密码"
// @Success 200 {object} EdgeInstanceList
// @Router /api/login/{user_id} [POST]
func Login(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("hello"))
}

https://cdn.xiaobinqt.cn/xiaobinqt.io/20220519/e46042ea6a5e4ce8bd4c85ec34223d9f.png?imageView2/0/q/75|watermark/2/text/eGlhb2JpbnF0/font/dmlqYXlh/fontsize/1000/fill/IzVDNUI1Qg==/dissolve/52/gravity/SouthEast/dx/15/dy/15
效果_01

https://cdn.xiaobinqt.cn/xiaobinqt.io/20220519/c068d1585a49494992af4e7993a5a4f8.png?imageView2/0/q/75|watermark/2/text/eGlhb2JpbnF0/font/dmlqYXlh/fontsize/1000/fill/IzVDNUI1Qg==/dissolve/52/gravity/SouthEast/dx/15/dy/15
效果_02