go generate未触发主因是//go:generate注释未紧邻package声明(中间不能有空行或import);其他坑包括gen.go缺main函数、相对路径错误、buf插件名/版本不匹配、sqlc dialect配置错误、生成目录冲突等。

go generate 为什么没触发?
多数人写完 //go:generate 注释后执行 go generate 却没反应,根本原因是:注释必须紧贴在包声明上方、且不能有空行隔开。Go 只扫描当前目录下所有 *.go 文件中「紧邻 package 声明的 //go:generate 行」,其他位置(比如函数里、结构体后)一概忽略。
常见踩坑点:
- 注释和
package main之间夹了空行或 import 块 —— 直接失效 - 用了
//go:generate go run gen.go,但gen.go本身没加package main或缺少main()函数 —— 报no main module - 路径写相对路径如
./scripts/gen.sh,而go generate默认在当前包路径执行,不是项目根目录 —— 权限或路径错误
buf + protoc-gen-go-grpc 生成 gRPC 代码总报错
用 buf generate 调用 protoc-gen-go-grpc 时常见 unknown plugin "go-grpc" 或生成文件为空,本质是插件未正确注册或版本不匹配。
实操要点:
-
buf.gen.yaml中plugin的name必须和二进制名一致:go-grpc对应protoc-gen-go-grpc,不是grpc-go或go_grpc -
protoc-gen-go-grpc版本要和google.golang.org/grpc兼容 —— v1.47+ 推荐用protoc-gen-go-grpc@v1.3.0,老项目用v1.2.0更稳 - 如果本地装了多个
protoc-gen-*插件,buf默认只认$PATH下的;别把插件放~/go/bin却忘了export PATH=$PATH:~/go/bin
sqlc 生成 DAO 层代码后编译失败
sqlc 生成的 models.go 和 queries.sql.go 编译不过,大概率是 SQL 模板里用了数据库特有语法(比如 PostgreSQL 的 RETURNING *),但 sqlc.yaml 里 dialect 配成了 mysql。
关键检查项:
-
sqlc.yaml的dialect必须和实际数据库严格一致:postgresql≠postgres,mysql不支持ON CONFLICT - SQL 文件里若含占位符如
$1,dialect: postgresql才认;MySQL 得用?,否则生成的Scan方法参数顺序错乱 -
sqlc默认不导出字段(首字母小写),若结构体字段要被外部包访问,得在 SQL 注释里加-- name: GetUser :one后手动改字段名首字母大写,或配emit_json_tags: true避免反射失败
Makefile 里并行跑 go generate 和 sqlc 容易出竞态
多个生成命令写在同一个 make generate 目标里,比如先 go generate 再 sqlc generate,但两者都写入同一目录下的 gen/,偶尔出现文件被删或覆盖,尤其在 CI 环境下。
稳妥做法:
- 给每个生成器分配独立输出目录:
sqlc输出到internal/sqlc/,go generate输出到internal/gen/,避免路径冲突 - 用
make -j1 generate强制串行,别信默认并行 ——go generate本身不保证并发安全 - 在
go.mod里加//go:build ignore到生成器脚本(如gen.go),防止它被go build误扫,导致依赖循环
生成工具链越重,越要盯住输入/输出边界和执行顺序。没人会帮你校验 buf 是否真读了你改过的 proto,还是 cached 了旧版本 —— 每次怀疑生成结果不对,先 buf cache clean。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











