Buf 能替代 protoc 不是其增强版,而是从项目结构、校验规则、生成流程三方面重构 Protobuf 工程实践,强制通过 buf.yaml 统一配置 roots、breaking 和 version,实现可验证、可 CI 的标准化协作。

Buf 为什么能替代 protoc
buf 不是 protoc 的“增强版”,而是从项目结构、校验规则、生成流程三方面重构了 Protobuf 工程实践。它强制要求 buf.yaml 配置,把 proto 文件组织、lint 规则、生成目标全收口,避免团队靠文档或口头约定来维护一致性。
protoc 本身只是编译器,不关心你 proto 放哪、是否重复 import、字段命名是否统一;buf 把这些都变成可配置、可验证、可 CI 的环节。真正省掉的不是命令行参数,是人肉 review 和事后修复成本。
初始化 buf.yaml 必须填的三项
空项目跑 buf init 只生成骨架,实际生效靠这三项:
-
version:必须是v1,写成v1beta1或留空会报错unknown config version -
breaking:至少配一个use,比如["FILE"],否则buf breaking直接跳过检查 -
build:必须指定roots,例如["proto"],否则buf build找不到 .proto 文件(哪怕它们就在当前目录)
常见错误现象:buf build 报 no files to compile,八成是 roots 指错了路径,或者 proto 文件没放在 roots 下的子目录里。
立即学习“go语言免费学习笔记(深入)”;
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
用 buf generate 替代 protoc --go_out 的关键配置
buf 不调用 protoc 二进制,而是通过插件机制对接 generator(比如 bufbuild/plugins/protoc-gen-go)。核心在 generate 字段:
-
plugin名必须和官方插件仓库名一致,例如go对应bufbuild/plugins/protoc-gen-go,不能写成protoc-gen-go -
out路径是相对于当前工作目录的,不是相对于 proto root;paths控制哪些 proto 文件参与生成,留空则全部参与 - Golang 生成需额外加
opt:"module=github.com/yourorg/yourrepo",否则生成的go_package会默认 fallback 到./,导致 import 冲突
示例片段:
generate:
- plugin: go
out: internal/pb
opt: ["module=github.com/yourorg/yourrepo"]buf lint 报 WARNING 但 CI 过不去?看清楚 level
buf 默认把很多规则设为 WARNING(比如 FIELD_LOWER_SNAKE_CASE),而 buf lint 命令默认只输出不中断;但 CI 中常配 buf lint --error-format=json | jq 或直接用 set -e,导致 WARNING 当 ERROR 处理。
- 临时绕过:加
--error-format=short并确保 shell 不因非零退出码失败 - 长期方案:在
buf.yaml的lint下显式设ignore_only或改use列表,比如去掉PACKAGE_LOWER_SNAKE_CASE如果你们接受package api_v1; - 注意:有些规则如
ENUM_NO_ALLOW_ALIAS是ERROR级别,不修复就过不了buf lint
最容易被忽略的是:buf 的 lint 规则是可组合的,default preset 包含 20+ 条,但团队往往只关注命名风格,忘了 RPC_REQUEST_RESPONSE_UNIQUE 这类影响 gRPC 接口设计的硬性约束。

















