swag init 找不到 handler 的根本原因是静态扫描机制失效:未用 -g 指定入口文件导致无法递归解析 import 依赖,handler 函数缺少紧邻声明的 // @summary 和 // @router 注释,或函数未导出、位于测试文件中。

Go 语言没有内置 Swagger 文档生成能力,swag 是当前唯一稳定、可落地的方案——它不靠运行时反射,而是静态扫描源码注释;不写对注释格式、不指定入口文件、不带 json tag 的结构体字段,文档就必然残缺或空白。
swag init 找不到 handler 函数?检查扫描路径和入口文件
常见现象是 docs/swagger.json 里 "paths": {},或者只生成了 /swagger/* 路由,业务接口全无。根本原因不是代码有 bug,而是 swag init 默认只扫描当前目录及子目录下、与入口文件同 module 的 .go 文件。
- 必须用
-g显式指定入口文件,例如swag init -g cmd/app/main.go,否则它不会顺着import递归解析internal/handler或pkg/api中的函数 - handler 所在文件不能是
package main(除非它真包含路由注册逻辑),推荐统一用package handler或package api - 如果 handler 分散在多个目录,加
-d多次指定:例如swag init -g main.go -d internal/handler -d pkg/api - 别把 handler 放在
_test.go文件里——swag默认跳过测试文件
@Summary 和 @Router 缺一不可,注释必须紧贴函数声明
swag 只认以 // @ 开头、大小写严格匹配的注释块。漏掉 @Summary 或 @Router,该接口直接被忽略,且不报错、不提示。
- 注释块必须顶格、紧贴 handler 函数上方,中间不能有空行;写在
func main()里或闭包中无效 -
@Router的路径和 HTTP 方法必须与实际路由一致,例如// @Router /api/users [get]对应r.GET("/api/users", ListUsers) -
@Param必须写清位置:path/query/body,类型只能是string、int、bool等基础名,不能写uuid.UUID或int64 -
@Success 200 {object} models.User中的models.User必须带包名,且该结构体需已import,字段需导出并带json:tag
生成 docs/ 后 404?你没挂载 Swagger UI 路由
swag init 只生成静态资源(docs/swagger.json、docs/docs.go),不会自动注册 HTTP 路由。访问 /swagger/index.html 404,99% 是因为没手动注入 handler。
- 确保已
import _ "your-module-name/docs"(注意下划线导入,触发init()) - Gin 中注册方式必须是:
router.GET("/swagger/*any", ginSwagger.WrapHandler(docs.Handler)),*any不能省,否则 CSS/JS 加载失败 - 别用
router.Static("/swagger", "./docs")—— Swagger UI 是 SPA,依赖 History API 回退,必须走ginSwagger.WrapHandler - 若用
net/http,需调用http.Handle("/swagger/", http.StripPrefix("/swagger/", swaggerFiles.Handler))
中文乱码、字段全空、响应显示 “object”?检查三个硬性条件
文档加载后中文变 \u4f60\u597d,或点开 Schema 全是空对象,不是配置问题,而是代码层未满足 swag 解析器的硬性要求。
- 所有含 Swagger 注释的 Go 文件编码必须是 UTF-8(用
file -i handler.go检查,VS Code 右下角可切换) - 结构体字段必须导出(首字母大写),且每个要展示的字段都得有
json:tag,例如Name string `json:"name"`;json:"-"或小写字段名会被跳过 - 如果结构体在另一个 module,需在
main.go顶部加// @modelsPackage github.com/yourname/project/models,否则swag找不到定义
最易被忽略的一点:swag init 不会检测结构体字段变更。改了 User.Name 为 FullName 却忘了重跑命令,docs/docs.go 里仍引用旧字段名,编译直接失败。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











