应使用 swag 工具从 Go 代码注释自动生成 OpenAPI 文档,而非手写 YAML;需严格遵循注释格式(如 @router、@success 大小写敏感),显式指定扫描路径与 internal 包解析,并正确配置 Host、BasePath 及静态资源路由以确保文档可用性。

用 Swagger 生成 Go HTTP 服务的 OpenAPI 文档,但别直接写 YAML
Go 微服务的 API 文档不该手写 OpenAPI YAML,而应从代码注释自动生成。Swagger(swag 工具)是目前最轻量、兼容性最好的选择——它不侵入业务逻辑,也不依赖运行时反射,只扫描特定格式的注释块。
常见错误是把 @success 写成 @Success(大小写敏感),或漏掉 @router 导致该接口完全不出现在文档中。另外,swag init 默认只扫 ./...,如果你的 handler 分散在 internal/handler 和 api/v1 两个包里,必须显式指定:
swag init -g cmd/myapp/main.go -o ./docs --parseDependency --parseInternal-
--parseInternal是关键:否则不会解析internal/下的结构体定义 - 所有被引用的请求/响应结构体,必须导出(首字母大写),且字段带
json:tag
给 Gin/Gorilla 路由加注释时,@router 和 @summary 缺一不可
Gin 的 GET("/users/:id", handler) 在文档里不会自动变成 /users/{id}——你得靠 @router 显式声明路径和方法,否则生成的路径还是 /users/:id,OpenAPI Validator 会报错。
示例注释块(放在 handler 函数上方):
立即学习“go语言免费学习笔记(深入)”;
// @Summary Get user by ID
// @Description Retrieve a user with given ID
// @Tags users
// @Accept json
// @Produce json
// @Param id path string true "user ID"
// @Success 200 {object} model.UserResponse
// @Failure 400 {object} model.ErrorResponse
// @Failure 404 {object} model.ErrorResponse
// @Router /users/{id} [get]
func GetUser(c *gin.Context) { ... }
-
@Router必须含 HTTP 方法([get]),且路径中的变量名({id})要和@Param里的 name 一致 -
@Param类型写path还是query,直接影响参数位置和必填校验逻辑 - 如果用了 Gin 的中间件做鉴权,
@Security可声明BearerAuth,但需配套在@title前加@securityDefinitions.apikey
嵌套结构体、泛型返回值、error code 文档化最容易漏掉
Go 没有类型擦除,map[string]interface{} 或 json.RawMessage 会被 swag 当作空对象;泛型如 Result[T] 则直接无法解析——这些都得手动用 @Schema 注解覆盖。
- 对
type Response[T any] struct { Data T `json:"data"` },需在函数注释里加:// @Success 200 {object} Response{Data=model.User} - 错误码不能只靠
@Failure 404,要明确写出响应体:@Failure 404 {object} model.ErrorResponse,否则 UI 里看不到 error 字段说明 - 嵌套结构体字段若含指针(
*string),swag默认标为 required,实际可能为 null——得在结构体字段注释加// swagger:nullable
部署时让 /swagger/index.html 正确加载静态资源
生成的 docs/docs.go 里,docs.SwaggerInfo.Host 默认为空,导致前端请求 http://localhost:8080/swagger/doc.json 时 404——因为浏览器按相对路径拼 URL,而没配 Host 就会指向当前域名,不是你的 API 服务地址。
- 启动前设
docs.SwaggerInfo.Host = "api.example.com:8080"(开发环境可用"localhost:8080") - 用 Gin 时,别直接
router.StaticFile("/swagger/index.html", "./docs/swagger/index.html"),而要用ginSwagger.WrapHandler(swaggerFiles.Handler),它自动处理/swagger/*any所有子路径 - 如果 API 网关(如 Kong)前置了 /v1 前缀,需同步改
docs.SwaggerInfo.BasePath = "/v1",否则所有请求路径会少一层
文档能跑起来只是第一步;真正难的是保持注释和代码同步——每次改了 UserResponse 字段,却忘了更新 @Success 里的结构体引用,生成的文档就悄悄失效了。


















