swag init扫不到接口的根本原因是未显式指定扫描路径(-d)和入口文件(-g),导致handler文件未被识别;handler须在非main包中、有合法package声明且无语法错误,注释需紧贴函数、含@Summary和@Router,结构体须导出并带json tag。

Go 微服务里用 Swagger 生成接口文档,实际只有 swag 这一个能稳住的方案——它不靠运行时反射,而是静态扫注释,改完注释跑一次 swag init 就更新,没延迟、不重启服务。
swag init 扫不到接口?路径和入口文件必须显式指定
常见现象:执行完 swag init,docs/swagger.json 里 "paths":{},Swagger UI 显示首页但空荡荡。根本原因不是代码错,是 swag 根本没看到你的 handler 文件。
-
swag init默认只扫当前目录及子目录下、且属于同一 Go module 的.go文件;微服务通常把 handler 拆在internal/handler、api/v1、pkg/route等路径,必须用-d显式指定:swag init -d internal/handler -d api/v1 - 路由注册逻辑常在
cmd/app/main.go或app/server.go,得用-g指定入口:swag init -g cmd/app/main.go,否则跨包 import 的 handler 不会被递归解析 - 被扫描的文件不能是
package main(除非它真写了r.POST(...)),推荐把路由逻辑单独放在package router或package api - 所有 handler 文件必须有合法
package xxx声明,且不能含语法错误,否则整文件被跳过
@Param 和 @Success 写错类型?swag 不认 Go 类型系统
报错类似 cannot find type definition for "uuid.UUID" 或 unknown type "string",本质是 swag 的类型解析器和 Go 编译器不一致:它只识别基础类型名和已用 // @Model 显式声明过的 struct。
- 路径/查询/请求头参数只能写
string、int、bool、float64—— 别写int64、uint或uuid.UUID - 请求体(
in: body)必须指向一个已定义的 struct,且该 struct 上方需有// @Model注释,例如:// @Model type UserCreate struct { Name string `json:"name"` Age int `json:"age"` } -
@Success 200 {object} model.UserResponse—— 结构体必须导出(首字母大写),字段必须带json:tag,否则字段不会出现在 schema 中 - 数组参数不能简写为
type: []string,得写:@Param ids query array true "ID列表" collectionFormat:multi items.type:string
中文乱码、响应体显示 “object”、字段全空?检查三个硬性条件
文档加载后中文变 \u4f60\u597d,或点开响应 schema 全是空对象,大概率不是配置问题,而是代码层面没满足 swag 的硬性要求。
立即学习“go语言免费学习笔记(深入)”;
- 源文件编码必须是 UTF-8(无 BOM),Windows 下路径含中文或空格会导致解析失败,建议项目路径纯英文、无空格
- 所有用于请求/响应的结构体字段必须导出(大写首字母),且
json:tag 不能是-(如ID int `json:"-"`→ 该字段完全不出现在文档中) - 嵌套结构体也必须是导出类型,不能是
map[string]interface{}或interface{}——swag无法解析,会显示为object无具体内容 -
@Param user body model.User true "用户信息"中的model.User必须带完整包名,不能只写User;若返回指针,要写*model.User
gin-swagger 页面打开空白或 404?路由注册顺序错了
ginSwagger.WrapHandler(swaggerFiles.Handler) 必须在所有业务路由注册之后、r.Run() 之前挂载,否则中间件匹配不到 /swagger/*any 路径。
- 错误写法:
r := gin.New()后立刻注册 swagger 路由,再加载其他 group —— 此时gin.Default()的 logger/recovery 中间件还没生效,可能导致 panic 不被捕获,swagger 路由也失效 - 正确顺序:先
r := gin.Default(),再r.Group()加业务路由,最后r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler)) -
/*any是 Gin 的通配符语法,不能写成/*或/swagger/—— 否则子路径如/swagger/index.html无法命中 - 若用 Docker 构建镜像,必须显式
COPY docs/ docs/,否则容器内docs目录不存在
最易被忽略的是:每次修改注释后必须重新运行 swag init,浏览器还要硬刷新(Ctrl+Shift+R),否则缓存会掩盖更新。另外,docs/docs.go 里硬编码的 import 路径必须和 go.mod 第一行模块名完全一致,差一个字符都会编译失败。


















