使用 swag 来给 go 项目添加自动化构建文档。
安装
# 安装 swag 命令行工具
go install github.com/swaggo/swag/cmd/swag@latest
# 在项目中安装
go get -u github.com/swaggo/gin-swagger
go get -u github.com/swaggo/files
cli
在包含 main.go 文件的项目根目录运行 swag init 。这将会解析注释并生成重要的文件(如 docs 文件夹和 docs/docs.go) 。
# 通常使用
swag init
# 若通用 API 未写在 main.go
swag init -g cmd/docs.go
在输入后可以使用 fmt 格式化 SWAG 注释 (需要升级到最新版本):
swag fmt
如果使用的 air 可以在 .air.toml#pre_cmd 设定 ["swag fmt", "swag init -d ./cmd,./internal -o ./docs -g ./docs.go"] 来自动化更新文档。
.air.toml
pre_cmd = ["swag fmt", "swag init -d ./cmd,./internal -o ./docs -g ./docs"]
通用注释
这类注释通常放到项目的主入口文件(如 main.go )中,用于定义 API 的全局信息。
如果未放置在默认位置(
main.go ),那么需要使用 -g 指定该代码片段放置位置swag init -g cmd/docs.go
| 标签 | 说明 | 示例 |
|---|---|---|
@title | API 文档的标题 | @title 我的项目 API |
@version | API 的版本号 | @version 1.0 |
@description | API 的简要描述 | @description 这是一个示例项目 |
@termsOfService | API 的服务条款 | @termsOfService xxx/terms |
@contact.name | 联系方式名称 | @contact.name API 支持 |
@contact.url | 联系网址名称 | @contact.url xxxx/support |
@contact.email | 联系邮箱名称 | @contact.email Mr.MudBean@outlook.com |
@license.name | 许可证名称 | @license.name Apache 2.0 |
@license.url | 许可证网址 | @license.url xxx |
@host | API 服务的主机地址 | @host localhost:8080 |
@BasePath | API 的基础路径 | @BasePath /api/v1 |
@securityDefinitions.basic | 安全定义 | @securityDefinitions.basic basicAuth |
@externalDocs.description | 外部文档描述 | @externalDocs.description OpenAPI |
@externalDocs.url | 外部文档网址 | @externalDocs.url xxx |
- cmd/doc.go
- go.code-snippets
cmd/docs.go
package main
// @title 我的项目
// @version 1.0.2
// @description 这是一个使用 Swaggo 生成的 API 文档的 Gin 项目
// @termsOfService https://github.com/swaggo/swag/blob/master/README_zh-CN.md
// @contact.name API 支持
// @contact.url https://lmssee.com/support
// @contact.email Mr.MudBean@outlook.com
// @license.name Apache 2.0
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html
// @host localhost:9456
// @BasePath /api/v1
// @securityDefinitions.basic BasicAuth
go.code-snippets
{
"Swagger General Notes": {
"prefix": "swagger-general",
"body": [
"// @title ${1:个人项目}",
"// @version ${2:1.0.0}",
"// @description ${3:这是一个使用 Swaggo 生成的 API 文档的 Gin 项目}",
"// @termOfService ${4:https://github.com/swaggo/swag/blob/master/README_zh-CH.md}",
"",
"// @contact.name ${5:API 支持}",
"// @contact.url ${6:https://lmssee.com/support}",
"// @contact.email ${7:Mr.MudBean@outlook.com}",
"",
"// @license.name ${8:Apache 2.0}",
"// @license.url ${9: http://www.apache.org/licenses/LICENSE-2.0.html}",
"",
"// @host ${10:localhost}:${11:9463}",
"// @BasePath ${12:/api/v1}",
"//",
"// @securityDefinitions.basic ${13:BasicAuth}",
"",
"// @externalDocs.description ${14:OpenAPI}",
"// @externalDocs.url ${15:https://swagger.io/resources/open-api/}"
],
"scope": "go",
"description": "构建 swagger 在 go 项目中的通用注释(一般仅使用一次)"
}
}
API 接口注释
这一类注释直接写在 HTTP Handler 函数上方,用于描述具体的接口。
| 标签 | 说明 | 示例 |
|---|---|---|
@Summary | 接口的简短摘要 | @Summary 创建新用户 |
@Description | 接口的详细描述 | @Description 根据传入参数创建一个用户 |
@Tags | 用于对接口进行分组 | @Tags 用户管理 |
@Accept | 请求体的数据格式 | @Accept json |
@Produce | 响应体的数据格式 | @Produce json |
@Param | 请求参数 | @Param id path int true "用户 ID" |
@Success | 成功响应 | @Success 200 {object} model.User |
@Failure | 失败响应 | @Failure 404 {object} model.Error |
@Router | 请求的路径和方法 | @Router /users/{id}/ [get] |
- internal/test/handler.go
- go.code-snippets
internal/test/handler.go
// Getting go doc
//
// @Summary 获取
// @Description 简单测试 Get
// @Tags 测试
// @Accept json
// @Produce json
// @Success 200 {object} testResponse "成功响应"
// @Failure 400 {object} errno.SwagBadRequest "参数错误"
// @Failure 500 {object} errno.SwagServerError "服务器错误"
// @Router /test [get]
{
"Swagger Controller Notes": {
"prefix": "swagger-controller",
"scope": "go",
"description": "构建通用的 swagger 在 controller 山的接口注释",
"body": [
"// ${1:add} go doc",
"// @Summary ${2:简短描述}",
"// @Description ${3:接口描述(可选)}",
"// @Tags ${4:接口分组,如用户管理}",
"// @Accept ${5:json}",
"// @Produce ${6:json}",
"// @Param ${7:paramName} ${8:path/query/body/header}
${9:string/int/object} ${10:true/false} \"${11:参数说明}\"",
"// @Success 200 {object} ${12:响应结构体,如 UserResponse} \"成功响应\" ",
"// @Failure 400 {object} ${13:errno.SwagBadRequest} \"参数错误\"",
"// @Failure 500 {object} ${14:errno.SwagServerError} \"服务器错误\"",
"// @Router ${15:/api/v1/resource} [${16:get/post/put/delete}]"
]
}
}
@Param 参数详解
完成格式:
// @Param 参数名 参数位置 数据类型 是否必填 "描述"
| 参数部分 | 可选值 | 示例 |
|---|---|---|
| 参数名 | 自定义 | id 、 username 、 data |
| 参数位置 | path/query/formData/body/header | --- |
| 数据类型 | 基本类型/结构体 | int、 string 、 bool 、 UserRequest |
| 是否必填 | true/false | true |
| 描述 | 字符串 | "用户唯一标识符" |
示例
// @Param id path int true "用户 ID"
// @Param name query string false "用户名"
// @Param user body userRequest true "用户信息"
// @Param Authorization header string true "认证令牌"
| 位置 | 说明 | 路由 |
|---|---|---|
path | URL 路径参数 | /users/{id} |
query | URL 查询字符串 | /users?name=Tom&page=1 |
formData | 表单数据,包括文件上传 | multipart/form-data |
body | 请求体(JSON/XML) | Content-Type: application/json |
header | HTTP 头 | --- |
cookie | Cookie | --- |
除了基础的 required ,Swaggo 支持直接写在 @Param 或结构体中,用于生成更详细的参数约束说明(尽然 Swaggo 本身不执行校验,但文档会显示这些规则)
| 标签 | 说明 | 示例 |
|---|---|---|
Enum | 限制参数的枚举值 | @Param status query string false "状态" Enums(active, inactive) |
Default | 参数的默认值 | @Param page query int false "页码" Default(1) |
Minimum/Maximum | 数值范围(包含边界) | @Param age query int false "年龄" Minimum(0) Maximum(120) |
MinLength/MaxLength | 字符串长度限制 | @Param keyword query string false "关键字" MinLength(3) MaxLength(20) |
Format | 指定数据格式 | @Param date query string false "日期" Format(date-time) |
CollectionFormat | 数组格式 | @Param ids query []int false "ID 列表" CollectionFormat(multi) |
如果不想为简单的请求体专门创建一个 Struct ,可以直接在注释中写 JSON 结构:
// @Param user body object true "用户信息"
// @Param user.body.name string true "用户名"
// @Param user.body.age int false "年龄"
@Success 成功响应
格式说明:
// @Success 状态码 {返回类型} 数据类型 "描述"
示例:
// 返回对象
// @Success 200 {object} UserResponse "成功返回用户信息"
// @Success 201 {object} CreateUserResponse "创建成功"
// @Success 204 "删除成功,无返回内容"
// 返回数组
// @Success 200 {array} User "返回用户列表"
// @Success 200 {array} model.User "返回模型数组"
// 返回分页数据
// @Success 200 {object} Pagination{data=[]User} "分页数据"
// @Success 200 {object} CommonResponse{data=[]User} "通用返回格式"
// 基本类型
// @Success 200 {string} string "返回字符串"
// @Success 200 {int} int "返回整数"
// @Success 200 {boolean} bool "返回布尔值"
// @Success 200 {file} file "返回文件"
// 自定义响应头
// @Success 200 {string} string "操作成功" Header(X-RateLimit-Limit,int,请求限制) Header(X-RateLimit-Remaining,int,剩余次数)
// 自定义分页结构
type Pagination struct {
Page int `json:"page"`
PageSize int `json:"page_size"`
Total int64 `json:"total"`
Data interface{} `json:"data"`
}
// 在注释中使用
// @Success 200 {object} Pagination{data=[]User,total=int64} "分页用户列表"
@Failure 错误响应
格式说明:
// @Failure 状态码 {返回类型} 数据类型 "描述"
完整示例:
// @Failure 400 {object} ErrorResponse "请求参数错误"
// @Failure 401 {object} ErrorResponse "未授权"
// @Failure 403 {object} ErrorResponse "禁止访问"
// @Failure 404 {object} ErrorResponse "资源不存在"
// @Failure 500 {object} ErrorResponse "服务器内部错误"
// 定义标准错误响应
type ErrorResponse struct {
Code int `json:"code"`
Message string `json:"message"`
Details string `json:"details,omitempty"`
}
// 多错误状态码
// @Failure 400,404,500 {object} ErrorResponse "错误响应"
// 无返回体
// @Failure 429 "请求过于频繁,请稍后重试"
// 带响应头
// @Failure 429 {string} string "请求过于频繁" Header(Retry-After,int,重试等待秒数)
@Router 路由定义
格式说明:
// @Router 路径 [HTTP 方法] [分组]
完整示例:
// 基本格式
// @Router /users [post]
// @Router /users/{id} [get]
// @Router /users/{id} [put]
// @Router /users/{id} [delete]
// 带路径参数
// @Router /users/{id}/orders/{order_id} [get]
// 查询参数(不在Router中定义)
// @Router /users [get] # 对应 /users?name=xxx&page=1
// 路由分组(可选)
// @Router /api/v1/users [get] [用户管理]
// RESTful风格示例
// 创建用户
// @Router /users [post]
// 获取用户列表
// @Router /users [get]
// 获取单个用户
// @Router /users/{id} [get]
// 更新用户
// @Router /users/{id} [put]
// 删除用户
// @Router /users/{id} [delete]
@Accept
swag 接受多有正确的 MIME 类型,即使匹配 */*
| Alias | MIME TYPE |
|---|---|
json | application/json |
xml | text/xml |
plain | text/plain |
html | text/html |
mpfd | multipart/form-data |
x-www-form-urlencoded | application/x-www-form-urlencoded |
json-api | application/vnd.api+json |
json-stream | application/x-json-stream |
octet-stream | application/octet-stream |
png | image/png |
jepg | image/jpeg |
gif | image/gif |
event-stream | text/event-stream |
// 单个类型
// @Accept json
// @Accept xml
// @Accept mpfd # multipart/form-data
// @Accept x-www-form-urlencoded
// @Accept plain
// @Accept html
// 多个类型
// @Accept json
// @Accept xml
// 或
// @Accept json,xml
// 实际应用示例
// POST /users 创建用户
// @Accept json
// 对应 Header: Content-Type: application/json
@Produce
// 单个类型
// @Produce json
// @Produce xml
// @Produce plain
// @Produce html
// @Produce png
// @Produce pdf
// @Produce octet-stream # 二进制流
// 多个类型
// @Produce json
// @Produce xml
// 对应 Header: Content-Type: application/json 或 application/xml
// 根据客户端 Accept 头协商返回
// 常用组合
// @Accept json
// @Produce json
@Summary 和 @Description
// @Summary 简短摘要
// @Description 详细描述
// 支持多行
// 这是第二行描述
// 还可以使用Markdown格式
// - 列表项1
// - 列表项2
// 代码示例: `fmt.Println("hello")`
结构体字段注释
| 标签 | 说明 | 示例 |
|---|---|---|
example | 字段的示例值 | Name string json:"name" example:"张三" |
required | 标记字段为必填 | Email string json:"email" required:"true" |
enum | 定义字段的枚举值 | Status string json:"status" enum:"active,inactive" |
minimum/maximum | 数值的最小/最大值 | Age int json:"age" minimum:"0" maximum:"120" |
swaggerignore | 忽略该字段,不生成文档 | InternalID int swaggerignore:"true" |
// 请求体示例
// @Param request body CreateUserRequest true "创建用户请求" example({"name":"张三","age":20})
// 模型示例
type CreateUserRequest struct {
// 用户名
// Required: true
// Example: 张三
Name string `json:"name" binding:"required"`
// 年龄
// Minimum: 0
// Maximum: 150
// Example: 20
Age int `json:"age"`
// 邮箱
// Format: email
// Example: user@example.com
Email string `json:"email" binding:"required,email"`
}
安全与认证标签
如果 API 需要鉴权( 如 JWT 、 OAuth2 、 Basic Auth ),这可能需要下面的标签
| 标签 | 说明 | 示例 |
|---|---|---|
@SecurityDefinitions | 定义安全机制的类型(放在 main.go) | @SecurityDefinitions.apikey Bearer |
@in | 定义 Token 传递的位置(配合第一个) | @in header |
@name | 定义 Token 的 Header 名称(配合第一个) | @name Authorization |
@Security | 在具体的接口上声明需要哪种安全机制 | @Security Bearer |
// ------ main.go 文件 ------
// @SecurityDefinitions.apikey Bearer
// @in header
// @name Authorization
// ----- 在具体的 Handler -----
// @security Bearer
// @Summary 获取个人信息
自定义扩展标签
Swagger 规范允许使用 x- 开头的字段进行扩展。常用于对接云服务( 如 AWS API Gateway )或添加自定义元数据。
| 标签 | 说明 | 示例 |
|---|---|---|
@x-example | 为字段或响应提供具体的 JSON 示例 | @x-example {"id": 1 , "name": "test"} |
@x-nullable | 标记字段可以为 null | extensions: "x-nullable" 需要结合结构体标签 |
@x-codeSamples | 在文档中展示代码示例 | -- |
@x-tagGroups | 对左侧大的 Tags 进行分组显示 | --- |
// @x-codeSamples [
// @x-codeSamples { "lang": "curl", "source": "curl -X GET http://localhost:8080/users" },
// @x-codeSamples { "lang": "javascript", "source": "fetch('/users')" }
// @x-codeSamples ]
// @Router /users [get]