protoc-gen-go和protoc-gen-go-grpc必须匹配安装最新版(v1.30+),配合--go_out和--go-grpc_out分参数调用,并设置paths=source_relative及正确go_package路径,否则编译报错或导入失败。

直接用 protoc 命令加两个插件输出即可,不需要手写任何结构体或接口。关键不是“能不能生成”,而是插件版本、参数顺序和 go_package 路径是否对得上——错一个就编译报错或包导入失败。
protoc-gen-go 和 protoc-gen-go-grpc 必须都装对版本
这两个插件不能混用旧版和新版,尤其不能用 v1.26 之前的 protoc-gen-go 配合新版 protoc-gen-go-grpc。当前(2026 年)稳定组合是:
go install google.golang.org/protobuf/cmd/protoc-gen-go@latestgo install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
装完检查是否在 $PATH 里:protoc-gen-go --version 和 protoc-gen-go-grpc --version 都应返回带 v1.30+ 的版本号。如果提示 command not found,说明 GOBIN 没进环境变量,或者 go install 没成功。
--go_out 和 --go-grpc_out 参数必须分开且顺序不能颠倒
老教程里常见的 --go_out=plugins=grpc:. 已被彻底废弃,继续用会报错:--go_out: protoc-gen-go: plugins are not supported。正确命令是:
protoc --go_out=. --go_opt=paths=source_relative \ --go-grpc_out=. --go-grpc_opt=paths=source_relative \ api/greet.proto
注意点:
-
--go_out=.只生成.pb.go(消息结构体),不带 gRPC 逻辑 -
--go-grpc_out=.单独生成_grpc.pb.go(服务接口、客户端存根、服务注册函数) -
--go_opt=paths=source_relative确保生成的package和import路径与 proto 文件所在目录结构一致,否则go build找不到包
proto 文件里的 option go_package 必须写绝对导入路径
这一步最容易被跳过,但直接影响生成代码能否被正常 import。不能只写 option go_package = "greet";,而要写成:
option go_package = "./greet;greet";
含义是:生成的 Go 文件放在当前目录下的 greet 子目录中,包名为 greet。如果你的 proto 在 proto/greet/v1/greet.proto,那应该写:
option go_package = "proto/greet/v1;greetv1";
否则生成的 .pb.go 里会默认用 package greet,但文件实际在 ./proto/greet/v1/ 下,go mod tidy 时就会报 cannot find package。
生成的代码别直接提交到 git,但必须进 go.mod 依赖
生成的 *.pb.go 和 *_grpc.pb.go 是机器产物,不该手动修改,也不该长期留在 git 历史里——但它们又必须能被 go build 正确识别。推荐做法:
- 把 proto 放在
proto/目录下,生成代码统一放internal/pb/或api/ - 在
go.mod里确保已包含google.golang.org/protobuf和google.golang.org/grpc - CI 流程里加一步
protoc生成,本地开发用 Makefile 或脚本封装,避免每次手敲命令
最常被忽略的是:生成后不运行 go mod tidy,导致 grpc.ServiceRegistrar 或 proto.Message 类型未解析——这不是 protoc 的问题,是 Go 模块没拉齐依赖。











