news 2026/9/13 16:47:08

使用 buf 生成 gRPC 网关 Stub:grpc-gateway 项目的代码生成实践指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
使用 buf 生成 gRPC 网关 Stub:grpc-gateway 项目的代码生成实践指南

使用 buf 生成 gRPC 网关 Stub:grpc-gateway 项目的代码生成实践指南

【免费下载链接】grpc-gatewaygRPC to JSON proxy generator following the gRPC HTTP spec项目地址: https://gitcode.com/GitHub_Trending/gr/grpc-gateway

本文以 grpc-gateway 项目官方教程《Generating stubs using buf》为主线,完整讲解如何用 buf 替代 protoc 递归发现.proto文件、通过buf.yamlbuf.gen.yaml配置 Go 类型与 gRPC 服务 Stub 的生成,并对照仓库根目录的真实配置与 Makefile 中的调用方式,帮助读者一次性掌握从安装、配置到产出*.pb.go/*_grpc.pb.go的完整链路,为后续接入 grpc-gateway 网关代码生成打下基础。

为什么选择 buf 而非 protoc

在 grpc-gateway 教程体系中,生成 Stub 有两条路线:protoc路线与buf路线,两者的定位在生成 Stub 总览中有清晰说明:protoc是业界使用最广泛的经典生成工具,但学习曲线较陡;而buf是更年轻、以用户体验和速度为导向的工具,并且额外提供 lint(代码风格检查)与 breaking change detection(破坏性变更检测)——这两项能力是protoc本身不具备的。

buf 提供的 Protobuf 工具链能力包括:

  • lint:对.proto文件的命名规范、字段风格等进行静态检查;
  • breaking change detection:对比新旧版本,检测可能破坏二进制兼容性的改动;
  • generation:基于插件机制批量生成类型、服务与网关代码。

安装 buf

grpc-gateway 仓库自身通过 Go 工具链安装 buf,在 Makefile 中固定了版本:

go install github.com/bufbuild/buf/cmd/buf@v1.45.0

该命令将 buf 安装到$GOBIN(默认$GOPATH/bin),确保后续buf generate等子命令可用。除此之外,buf 官方也提供多种系统安装方式,具体可查阅其官方安装文档(当前仓库教程即指向该文档)。

用 buf.yaml 声明 Protobuf 模块

buf 与protoc最直观的差异在于输入文件的管理方式:protoc需要把每个.proto文件显式罗列在命令行上(参见 使用 protoc 生成 Stub 中的示例),而 buf 会在配置指定的文件层级下递归发现所有.proto文件并统一构建,无需逐个列举。

这个递归发现行为由buf.yaml控制。buf.yaml应检入(check in)到 Protobuf 文件层级(file hierarchy)的根目录,buf 会在运行时自动读取它(只要该文件存在)。此外,配置也可以通过命令行参数--config提供,它接受:

  • 指向.json.yaml文件的路径;
  • 或直接内联的 JSON / YAML 配置数据。

原教程给出的最小合法配置如下,将其放在 Protobuf 文件层级的根目录,例如仓库根目录下的proto/buf.yaml

version: v1 name: buf.build/myuser/myrepo
  • version:配置文件版本,目前为v1
  • name:模块的规范名称(Buf Schema Registry 风格),用于标识你的 Protobuf 模块。

仓库真实的 buf.yaml:不止两行

grpc-gateway 仓库根目录的 buf.yaml 是这一配置在实际大型项目中的完整形态,它展示了version/name之外的更多能力:

version: v1 name: buf.build/grpc-ecosystem/grpc-gateway deps: - buf.build/googleapis/googleapis breaking: use: - FILE lint: use: - DEFAULT ignore_only: DIRECTORY_SAME_PACKAGE: - examples/internal/proto/examplepb/a_bit_of_everything.proto # ... 其他按规则分组的忽略清单 allow_comment_ignores: true build: excludes: - bazel-grpc-gateway

对照教程要点,可逐项理解:

  • deps:声明外部依赖模块。这里的buf.build/googleapis/googleapis会被解析并写入 buf.lock(该文件为自动生成、勿手改,其中记录了远程模块的 owner、repository 与 commit 哈希,用于锁定版本);
  • breaking.use: [FILE]:以文件为单位检测破坏性变更;
  • lint.use: [DEFAULT]:启用默认 lint 规则集,并通过ignore_onlyENUM_VALUE_PREFIXFIELD_LOWER_SNAKE_CASEPACKAGE_DIRECTORY_MATCH等具体规则逐文件豁免——这正体现了教程所说的 lint 能力,也解释了为何仓库中允许存在部分不完全符合默认风格的历史 proto;
  • allow_comment_ignores: true:允许在.proto源码中用注释屏蔽 lint 规则;
  • build.excludes:构建时排除bazel-grpc-gateway目录,避免误把 Bazel 生成的目录纳入模块。

用 buf.gen.yaml 定义生成模板

配置好模块后,还需要一个生成模板文件buf.gen.yaml来告诉 buf:调用哪些插件、输出到哪里、传什么参数。原教程为 Go 类型与 gRPC Stub 给出的模板如下:

version: v1 plugins: - plugin: go out: proto opt: paths=source_relative - plugin: go-grpc out: proto opt: paths=source_relative
  • plugin: go/plugin: go-grpc:分别调用 Go 类型生成插件与 gRPC 服务定义生成插件,产出*.pb.go*_grpc.pb.go
  • out: proto:生成文件相对于proto目录输出;
  • opt: paths=source_relative:生成的 Go 文件与源.proto文件位于同一目录,避免按 Go import path 重建目录树。

仓库中的 v2 模板语法与 grpc-gateway 插件

grpc-gateway 根目录的 buf.gen.yaml 是教程示例的升级形态,使用了version: v2语法,并加入了 grpc-gateway 自己的两个生成插件:

version: v2 plugins: - remote: buf.build/protocolbuffers/go:v1.35.1 out: . opt: - paths=source_relative - remote: buf.build/grpc/go:v1.5.1 out: . opt: - paths=source_relative - require_unimplemented_servers=false - local: protoc-gen-grpc-gateway out: . opt: - paths=source_relative - allow_repeated_fields_in_body=true - local: protoc-gen-openapiv2 out: . opt: - allow_repeated_fields_in_body=true

与教程的 v1 示例相比,v2 语法的差异要点:

  • 插件来源字段:v1 用plugin: go表示本地插件;v2 区分为remote:(从 Buf Schema Registry 拉取远程插件,如buf.build/protocolbuffers/go:v1.35.1)与local:(调用本地已安装的可执行文件,如仓库自带的protoc-gen-grpc-gatewayprotoc-gen-openapiv2);
  • opt 列表化:v1 的opt是单个字符串,v2 中为字符串列表,可一次传多个参数(如paths=source_relativerequire_unimplemented_servers=false并列);
  • 网关插件protoc-gen-grpc-gateway生成*.pb.gw.go反向代理桩代码,protoc-gen-openapiv2生成 OpenAPI v2 描述文档——这正是 grpc-gateway 项目把“类型 Stub → gRPC Stub → HTTP 网关桩 → OpenAPI 文档”一次性串联起来的关键。

仓库内还有一批面向特定场景的模板文件,进一步展示了opt参数的定制能力:

  • enum_with_single_value.buf.gen.yaml:为protoc-gen-openapiv2传入omit_enum_default_value=true,控制单值枚举在 OpenAPI 输出中的呈现;
  • protoc-gen-openapiv2/options/buf.gen.yaml:为 Go 插件传入default_api_level=API_HYBRID等选项;
  • protoc-gen-openapiv3/buf.gen.yaml:使用本地protoc-gen-openapiv3插件产出 OpenAPI v3 描述。

运行 buf generate 并检查产物

配置完成后,在 Protobuf 文件层级根目录执行:

$ buf generate

buf 会读取根目录的buf.gen.yaml(也可用--template显式指定其他模板文件),递归构建模块内所有.proto文件,并为每个 protobuf package 生成:

  • *.pb.go:Go 类型定义;
  • *_grpc.pb.go:gRPC 服务接口与客户端/服务端桩。

在 grpc-gateway 仓库中,可以直观看到产物与源文件同目录落盘:例如 helloworld.proto 旁边就躺着 helloworld.pb.go、helloworld_grpc.pb.go 以及网关桩 helloworld.pb.gw.go 和 helloworld.swagger.json——这正是paths=source_relative的落地效果。

多模板并存的真实用法:--template

一个实际项目往往需要多套生成配置。grpc-gateway 的 Makefile 展示了这一实践:默认执行buf generate,随后用--template反复调用不同模板生成额外产物,例如:

buf generate --template ./examples/internal/proto/examplepb/openapi_merge.buf.gen.yaml buf generate --template ./examples/internal/proto/examplepb/standalone_echo_service.buf.gen.yaml buf generate --template ./examples/internal/proto/examplepb/unannotated_echo_service.buf.gen.yaml buf generate --template ./examples/internal/proto/examplepb/generate_unbound_methods.buf.gen.yaml buf generate --template ./examples/internal/proto/examplepb/use_go_template.buf.gen.yaml buf generate --template ./examples/internal/proto/examplepb/ignore_comment.buf.gen.yaml buf generate --template ./examples/internal/proto/examplepb/remove_internal_comment.buf.gen.yaml # 以及多组 visibility 规则模板、enum_with_single_value、proto3_field_semantics、 # opaque、protoc-gen-openapiv2/options、protoc-gen-openapiv3/options 等

由此可以看出,--template参数让“同一份 proto 源码、多份定制输出”成为可能——这正是教程中--config之外、buf 命令行灵活性的延伸,也是把 lint、breaking、多插件输出统一进 CI 流水线的基础。

依赖锁定与版本管理:buf.lock

buf.yaml声明了deps后,首次运行相关命令会生成 buf.lock。该文件由 buf 自动维护并应检入版本库,其内容锁定远程模块的确切提交,保证团队成员生成结果一致:

# Generated by buf. DO NOT EDIT. version: v1 deps: - remote: buf.build owner: googleapis repository: googleapis commit: 62f35d8aed1149c291d606d958a7ce32

在 grpc-gateway 中,googleapis 依赖为*.proto中的google.api.http等注解提供了类型来源——这是 grpc-gateway 路由映射(HTTP annotation)得以编译的基础。结合 go.mod 中的 Go 模块依赖,buf 生态的模块锁定(buf.lock)与 Go 生态的模块锁定(go.sum)共同构成了完整的可复现构建链路。

从 Stub 到网关:完整的接入路径

生成 Stub 只是 grpc-gateway 开发流程的第一步。教程的下一步指向 creating_main.go,即编写入口代码把 gRPC 服务与 HTTP 网关装配起来。若要从零走通全流程,建议按以下顺序阅读本教程系列:

  1. 教程导览与简单 Hello World 示例建立整体认知;
  2. .proto中加入 google.api.http 注解,声明 HTTP 路由映射;
  3. 按本文方式用 buf(或 protoc)生成类型与 gRPC Stub,再叠加 grpc-gateway 与 openapiv2 插件生成网关桩与 API 文档;
  4. 参考 creating_main.go 组装服务端与网关,最终落地运行。

小结

buf 通过buf.yaml(模块声明、lint 与 breaking 规则、依赖)+buf.gen.yaml(插件、输出路径、插件参数)取代了 protoc 繁琐的命令行文件罗列,并借助递归发现、远程插件与--template多模板机制,让 Stub 生成变得可声明、可复用、可锁定。grpc-gateway 仓库本身既是这套工具链的深度用户,也是最佳参考样例——从根目录的 buf.yaml、buf.gen.yaml、buf.lock 到 Makefile 中的全套生成指令,都可以直接对照本文的每一步进行验证与扩展。

【免费下载链接】grpc-gatewaygRPC to JSON proxy generator following the gRPC HTTP spec项目地址: https://gitcode.com/GitHub_Trending/gr/grpc-gateway

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/13 16:46:34

VMD-Attention-LSTM时间序列预测:原理、源码与参数调优实战

简介:基于VMD-Attention-LSTM的时间序列预测模型完整项目包,面向深度学习初学者及需要完成课程设计、毕业设计的学生。内含VMD变分模态分解、Attention注意力机制与双层LSTM网络的完整搭建代码,以及数据预处理、训练、预测和模型权重保存逻辑…

作者头像 李华
网站建设 2026/9/13 16:45:16

LKY Office Tools:3 步 5 分钟完成 Office 下载、安装、激活

LKY Office Tools:3 步 5 分钟完成 Office 下载、安装、激活 【免费下载链接】LKY_OfficeTools 一键自动化 下载、安装、激活 Office 的利器。 项目地址: https://gitcode.com/GitHub_Trending/lk/LKY_OfficeTools 刚重装完系统,发现没 Office 可…

作者头像 李华
网站建设 2026/9/13 16:44:02

数据分箱技术:特征工程中的核心预处理方法

1. 分箱技术概述与核心价值分箱(Binning)是数据预处理中的一项基础但至关重要的技术,尤其在特征工程和模型训练阶段扮演着关键角色。简单来说,分箱就是将连续变量离散化为有限个区间(称为"箱"或"桶&quo…

作者头像 李华