使用 swaggo 一键生成 API 文档
本文主要记录了如何在 Go 中使用 swaggo 根据注释自动生成 API 文档,以及如何使用条件编译来降低二进制文件大小。
原文作者: 意琦行
1. 概述
关于Swaggo
或许你使用过 Swagger, 而 swaggo 就是代替了你手动编写 yaml 的部分。只要通过一个命令
就可以将注释转换成文档,这让我们可以更加专注于代码。
接入流程
接入流程主要分为以下几个步骤:
- main 文件中添加注释-配置Server,服务信息
- controller 中添加注释-配置接口,接口信息
- swag init 生成 docs 目录
- 配置 handler 访问
- 访问测试
2. 演示
以 gin 框架为例,演示一下具体操作流程。
完整 Demo 见 Github
配置服务信息
main.go 中引入以下两个包:
|
|
并在 main 方法上添加以下注释描述 server:
具体可以添加哪些注释参考 通用API信息
|
|
配置接口文档
在每个接口的 controller 上添加注释以描述接口,就像下面这样:
具体可以添加哪些注释参考 API操作
|
|
swag init
需要先安装 swag,使用如下命令下载swag:
|
|
在包含main.go
文件的项目根目录运行swag init
。这将会解析注释并生成需要的文件(docs
文件夹和docs/docs.go
)。
|
|
注:swag init
默认会找当前目录下的 main.go 文件,如果不叫 main.go 也可以手动指定文件位置。
|
|
需要注意的是:swag init 的时候需要在项目根目录下执行,否则无法检测到所有文件中的注释。
比如在 /xxx 目录下执行 swag init 就只能检测到 xxx 目录下的,如果还有和 xxx 目录同级或者更上层的目录中的代码都检测不到。
init 之后会生成一个 docs 文件夹,这里面就是接口描述文件,生成后还需要将其导入到 main.go 中。
在 main.go 中导入刚才生成的 docs 包
加上之前导入的 gin-swag 相关的两个包,一共新导入了三个包。
|
|
配置文档handler
最后则是在 router 中增加 swagger 的 handler 了。
在 main.go 或其他地方增加一个 handler.
|
|
访问测试
项目运行起来后访问ip:port/swagger/index.html
即可看到 API 文档。
如果注释有更新,需要重新生成 docs 并重启服务才会生效。
3. 注释语法
具体语法见 官方文档,这里主要列出几个特殊的点。
Controller 注释支持很多字段,这里主要记录常用的。
tags:给 API 按照 tag 分组,便于管理。
accept、produce:API 接收和响应的 MMIE 类型。
param:接口请求参数,重要
- Syntax:
param name
,param type
,data type
,is mandatory?
,comment
attribute(optional)
- Syntax:
response、success、failure:API 响应内容,如果成功失败返回值不一样也可以通过 success、failure 分别描述。
- Syntax:
return code
,{param type}
,data type
,comment
- Syntax:
header:响应头
- Syntax:
return code
,{param type}
,data type
,comment
- Syntax:
router:接口路由
- Syntax:
path
,[httpMethod]
- Syntax:
主要详细记录一下 param 和 response 该怎么写。
param
语法:param name
,param type
,data type
,is mandatory?
,comment
attribute(optional)
参数类型:
- query
- path
- header
- body
- formData
数据类型:
- string (string)
- integer (int, uint, uint32, uint64)
- number (float32)
- boolean (bool)
- user defined struct
示例
|
|
以上示例就用到了 3 种参数:
- header 中的 Authorization
- body 中的 listModel
- queryString 中的 amount
由于是可以用结构体的,所以一般都建议使用结构体,这样比较简洁。
resp
语法:return code
,{param type}
,data type
,comment
返回值类型和数据类型和 param 都是一致的。
示例:
|
|
由于成功失败返回结构不同,所以分别处理。如果相同就直接用 response 即可。
不过大部分项目中应该会定义一个通用返回结构,比如这样的:
|
|
不同的接口,只需要替换里面的 Data 字段即可。
对于这种情况,如果每次都指定返回值是 Result 结构,就无法看到具体的响应了。但是肯定也不可能为每个接口重新生成一个对应的返回结构。
好在 swaggo 提供了 响应对象中的模型组合,可以自行组合结构体,以处理这种通用返回结果的情况。
对于固定返回结构来说这个就很方便,可以为每个接口指定对应的 data 字段内容。
具体如下:
|
|
还支持对象数组和原始类型作为嵌套响应
|
|
替换多个字段的类型。如果某字段不存在,将添加该字段。
|
|
对于上面的情况就可以这样处理了:
|
|
对于不同的接口,只需要替换其中的 data 字段即可。
4. FAQ
无法解析外部依赖
就是在项目引入了另外一个独立项目的数据结构体,在接口上配置
|
|
发现 swag init 无法正常生成想要的 swagger yaml 文件。 swag init 命令执行错误 cannot find type definition
解决方案
增加--parseDependency --parseInternal
两个参数同时在main.go
中导入我们依赖的包。
swag init –parseInternal –parseDependency
注:因为依赖的是外部包的内部结构,导致无法扫描到,同理,直接引入 go 内置的包也无法直接解析,也是需要这样处理一下。
无法引入内部依赖
有时候一个项目里依赖也无法解析:
|
|
swag init 时报错:
|
|
这个是因为同一个包里面定义了几个重名的结构体导致的,改名即可解决问题。
构建速度
在添加了--parseDependency
后生成速度明显减低,此时可以添加--parseDepth
参数指定数据结构深度来加快生成速度。
相关参数含义如下:
参数名 | 含义解释 |
---|---|
parseInternal | 解析内部依赖包,默认值: false |
parseDependency | 解析外部依赖包,默认值: false |
parseDepth | 解析依赖包深度,默认值:100 |
注:parseDepth 这个参数非常有用,如果你知道需要解析的数据结构深度,建议使用这个参数,swag 命令执行时间会大大缩短。
5. 优化
swag fmt
swaggo 提供了 swag fmt 工具,可以针对Swag的注释自动格式化,就像go fmt
,让注释看起来更统一。
示例:
|
|
排除目录(不扫描)示例:
|
|
指定 main.go
文件示例:
|
|
条件编译
swaggo 是直接 build 到二进制里的,会极大增加二进制文件的大小,一般在生产环境不需要将 docs 编译进去。
可以利用 go 提供的条件编译来实现是否编译文档。
在main.go
声明swagHandler
,并在该参数不为空时才加入路由:
同时,我们将该参数在另外加了build tag
的包中初始化。
条件编译只需要在对应文件首行加入 go:build xxx 即可,这样只有编译时指定 xxx tag 才会把该文件编译进去。
|
|
之后我们就可以使用go build -tags "doc"
来打包带文档的包,直接go build
来打包不带文档的包。
注:go 1.16 之前旧版条件编译语法为 //+build 1.16之后增加了新版语法 go:build
- 原文作者:长亭远望
- 原文链接:https://www.lvmo.work/2022/04/20/golang-package-swaggo.html
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议. 进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。