ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

goctl rpc 生成器指南:从 .proto 到完整 zRPC 服务的自动化代码生成

goctl rpc 生成器指南:从 .proto 到完整 zRPC 服务的自动化代码生成 后端RPC框架Web框架微服务API网关服务注册发现代码生成【免费下载链接】go-zeroA cloud-native Go microservices framework with cli tool for productivity.项目地址https://gitcode.com/GitHub_Trending/go/go-zero点击查看免费下载本篇技术指南围绕 go-zero 脚手架工具goctl的RPC 代码生成模块goctl rpc展开讲解如何仅凭一份.proto接口定义就自动生成一套完整可运行的 zRPC 微服务含 gRPC 桩代码、服务端、客户端、配置与业务逻辑骨架。读完本文你将掌握goctl rpc new / protoc / template三个子命令的完整用法与全部参数理解多服务、外部 proto import、流式 RPC、Google well-known types 等高级场景的生成行为并能结合仓库源码理解其底层生成管线。什么是 goctl rpcgoctl rpc是 goctl 脚手架中负责 RPC 服务代码生成的模块它的输入是.proto文件输出是一整套完整的 zRPC 服务工程。使用者只需要编写 proto 定义和业务逻辑其余所有样板代码boilerplate都由工具自动生成。其核心能力包括protoc 兼容与 protoc 完全兼容所有 protoc 参数都会原样透传pass-through外部 proto import支持跨目录、跨包的 proto import并自动解析传递依赖transitive dependency多服务支持允许在一个 proto 文件中定义多个 service并按服务名自动分组生成代码流式 RPC 支持同时支持服务端流式、客户端流式与双向流式三种 gRPC 流式模式Google well-known types自动识别受支持的google.protobuf.*类型并生成正确的 Go import客户端生成自动生成 RPC 客户端封装代码。从源码结构看该模块由三部分构成cli/命令参数解析与入口、parser/proto 文件解析与 import 依赖解析、generator/目录规划与各文件模板渲染。环境准备在开始使用前需要安装 protoc 以及两个 Go protoc 插件# 安装 protoc 插件 go install google.golang.org/protobuf/cmd/protoc-gen-golatest go install google.golang.org/grpc/cmd/protoc-gen-go-grpclatest生成过程依赖本机的protoc可执行文件goctl rpc在执行生成前会调用Generator.Prepare()见 generator/generator.go对 Go 环境、protoc 及 protoc-gen-go 的安装情况进行环境检测缺失时会在生成阶段报错提示。快速开始方法一一条命令即刻创建服务goctl rpc new greeter该命令会生成一个完整的项目结构greeter/ ├── etc/ │ └── greeter.yaml ├── greeter/ │ ├── greeter.pb.go │ └── greeter_grpc.pb.go ├── greeter.go ├── greeter.proto ├── greeterclient/ │ └── greeter.go └── internal/ ├── config/ │ └── config.go ├── logic/ │ └── pinglogic.go ├── server/ │ └── greeterserver.go └── svc/ └── servicecontext.go其中internal/logic是你的业务逻辑所在地internal/config存放服务配置结构internal/server是 gRPC 服务端注册代码internal/svc是依赖注入的 ServiceContextgreeterclient是给调用方使用的 RPC 客户端封装。从 cli/cli.go 的实现可以看到goctl rpc new会先在目标目录生成greeter.proto模板然后直接走与protoc命令相同的生成管线。方法二从 proto 文件生成先通过模板命令生成一个 proto 文件goctl rpc template -ouser.proto初始化输出目录并生成服务代码mkdir -p output cd output go mod init example.com/demo cd .. goctl rpc protoc user.proto \ --go_outoutput --go-grpc_outoutput --zrpc_outoutput \ --go_optmoduleexample.com/demo --go-grpc_optmoduleexample.com/demo \ --moduleexample.com/demo -I .goctl rpc template生成的模板内容基于内嵌的 rpc.tpl其中包含package、service、Request/Response消息骨架模板的package与serviceName会根据输出文件名自动填充见 prototmpl.gosyntax proto3; package user; option go_package./user; message Request { string ping 1; } message Response { string pong 1; } service User { rpc Ping(Request) returns(Response); }命令参考goctl rpc protoc从.proto文件生成 zRPC 服务代码goctl rpc protoc proto_file [flags]示例# 基本用法 goctl rpc protoc user.proto \ --go_outoutput --go-grpc_outoutput --zrpc_outoutput \ --go_optmoduleexample.com/demo --go-grpc_optmoduleexample.com/demo \ --moduleexample.com/demo -I . # 多服务模式 goctl rpc protoc multi.proto \ --go_outoutput --go-grpc_outoutput --zrpc_outoutput \ --go_optmoduleexample.com/demo --go-grpc_optmoduleexample.com/demo \ --moduleexample.com/demo -I . -m # 导入外部 proto goctl rpc protoc service.proto \ --go_outoutput --go-grpc_outoutput --zrpc_outoutput \ --go_optmoduleexample.com/demo --go-grpc_optmoduleexample.com/demo \ --moduleexample.com/demo -I . -I ./shared_protos # 使用 Google well-known types goctl rpc protoc service.proto \ --go_outoutput --go-grpc_outoutput --zrpc_outoutput \ --go_optmoduleexample.com/demo --go-grpc_optmoduleexample.com/demo \ --moduleexample.com/demo -I .flags 一览参数缩写类型默认值说明--zrpc_outstring必填zRPC 服务代码的输出目录--go_outstring必填protoc 生成的 Go 代码输出目录--go-grpc_outstring必填protoc 生成的 gRPC 代码输出目录--go_optstring透传给 protoc-gen-go 的选项如moduleexample.com/demo--go-grpc_optstring透传给 protoc-gen-go-grpc 的选项如moduleexample.com/demo--proto_path-Istring[]proto import 的搜索目录可重复指定--multiple-mboolfalse多服务模式--client-cbooltrue是否生成 RPC 客户端代码--stylestringgozero文件命名风格--modulestring自定义 Go module 名称--name-from-filenameboolfalse服务命名使用文件名而非package名--verbose-vboolfalse开启详细日志--homestringgoctl 模板目录--remotestring远程模板 Git 仓库 URL--branchstring远程模板分支其中--go_out、--go-grpc_out、--zrpc_out三个参数为必填缺失时ZRPC入口会分别抛出missing --go_out、missing --go-grpc_out、missing zrpc output的错误见 cli/zrpc.go。从 wrapProtocCmd 的实现可以看到--proto_path、--go_opt、--go-grpc_opt、--go_out、--go-grpc_out以及--plugin会被按顺序拼接到最终执行的protoc命令行中这就是所有 protoc 参数原样透传这一特性的实现基础。goctl rpc new快速创建一个完整的 RPC 服务项目goctl rpc new service_name [flags]flags 一览参数缩写类型默认值说明--stylestringgozero文件命名风格--client-cbooltrue是否生成 RPC 客户端代码--modulestring自定义 Go module 名称--verbose-vboolfalse开启详细日志--ideaboolfalse生成 IDE 项目标记--name-from-filenameboolfalse服务命名使用文件名而非package名--homestringgoctl 模板目录--remotestring远程模板 Git 仓库 URL--branchstring远程模板分支需要注意goctl rpc new的服务名参数不允许携带文件扩展名否则会报错unexpected ext见 cli/cli.go。goctl rpc template生成 proto 文件模板goctl rpc template -ooutput_file [flags]flags 一览参数类型说明-ostring输出文件路径必填--homestringgoctl 模板目录--remotestring远程模板 Git 仓库 URL--branchstring远程模板分支-o缺失时会直接返回missing -o错误同时该命令已标记为 deprecated官方提示未来将迁移为goctl rpc -o见 cli/cli.go。功能详解多服务模式--multiple当一个 proto 文件中定义了多个service时必须使用--multiple参数service SearchService { rpc Search(SearchReq) returns (SearchReply); } service NotifyService { rpc Notify(NotifyReq) returns (NotifyReply); }默认模式与--multiple模式的目录差异特性默认模式--multiple模式每个 proto 的服务数恰好 1 个1 个及以上客户端目录以服务名命名固定client/目录代码组织扁平结构按服务名分组--multiplefalse默认目录结构output/ ├── greeterclient/ │ └── greeter.go ├── internal/ │ ├── logic/ │ │ └── sayhellologic.go │ └── server/ │ └── greeterserver.go └── ...--multipletrue目录结构output/ ├── client/ │ ├── searchservice/ │ │ └── searchservice.go │ └── notifyservice/ │ └── notifyservice.go ├── internal/ │ ├── logic/ │ │ ├── searchservice/ │ │ │ └── searchlogic.go │ │ └── notifyservice/ │ │ └── notifylogic.go │ └── server/ │ ├── searchservice/ │ │ └── searchserviceserver.go │ └── notifyservice/ │ └── notifyserviceserver.go └── ...该行为与 generator/mkdir.go 中的目录规划逻辑一一对应默认模式下客户端目录由服务名转换而来如greeter→greeterclient多服务模式下客户端统一收敛到固定client/目录而logic/server下的子目录则按服务名分别建立。外部 proto import--proto_path通过-I/--proto_path可以指定额外的 proto 搜索目录支持以下场景同目录 importimport types.proto;子目录 importimport common/types.proto;外部目录 import导入项目外部的 proto 文件传递性 importA 导入 B、B 导入 C 时goctl 会递归解析完整依赖链跨包 import对于go_package值不同的文件自动生成正确的 Go import。# 在多个目录中搜索 proto 文件 goctl rpc protoc service.proto \ --go_outoutput --go-grpc_outoutput --zrpc_outoutput \ --go_optmoduleexample.com/demo --go-grpc_optmoduleexample.com/demo \ --moduleexample.com/demo \ -I . -I ./shared_protos -I /path/to/external_protos从源码层面看import 解析由 parser/import.go 的ResolveImports完成它以源文件为起点沿着每个import声明递归收集collectImports用visited集合防止循环依赖并将以google/开头的 well-known proto 自动跳过在 proto 路径中找不到的文件会被静默跳过与 protoc 自身行为一致避免系统级 proto 导致生成失败。解析得到的每个导入文件会记录其proto package、go_package与清洗后的 Go 包名ImportedProto见 parser/import.go供代码生成阶段跨包引用使用。服务命名规则默认情况下服务名取自 proto 的package名称例如package user;→ 服务名user。这使得多个 proto 文件可以共享同一个 packageprotos/ ├── user_base.proto # package user; ├── user_auth.proto # package user; └── user_profile.proto # package user;上述三个文件会统一生成到一个user服务中。若希望使用 proto 文件名作为服务名旧版行为则添加--name-from-filename参数。这一规则在 generator/mkdir.go 的determineServiceName中有明确实现默认取proto.Package.Namepackage 声明设置了--name-from-filename或 package 为空时回退为去除扩展名的 proto 文件名。流式 RPC三种 gRPC 流式模式全部支持service StreamService { rpc ServerStream(Req) returns (stream Reply); // 服务端流式 rpc ClientStream(stream Req) returns (Reply); // 客户端流式 rpc BidiStream(stream Req) returns (stream Reply); // 双向流式 }从 generator/ 目录下的logic.tpl、server.tpl等模板以及测试用例test/ 目录包含18 *.sh与16 *.proto测试资源可以看到流式接口会被生成对应的Stream接收/发送逻辑骨架业务层只需按 gRPC 流式语义填充处理代码。Google well-known typesgoctl 会自动识别并处理受支持的 Google protobuf well-known typesProto 类型Go 类型google.protobuf.Emptyemptypb.Emptygoogle.protobuf.Timestamptimestamppb.Timestampgoogle.protobuf.Durationdurationpb.Durationgoogle.protobuf.Anyanypb.Anygoogle.protobuf.Structstructpb.Structgoogle.protobuf.FieldMaskfieldmaskpb.FieldMaskgoogle.protobuf.*Valuewrapperspb.*Value这些类型可以直接用作 RPC 的参数类型goctl 会自动生成对应的 Go import。源码视角一次生成调用背后的完整管线goctl rpc protoc与goctl rpc new最终都会汇入同一个Generator.Generate方法见 generator/gen.go其执行顺序即为你最终看到工程目录的生成逻辑mkdir依据 proto 与--multiple标志规划并创建etc、internal/config、internal/logic、internal/server、internal/svc、pb、client等目录GenEtc生成 YAML 配置文件etc/*.yamlGenPb执行 protoc 命令生成*.pb.go与*_grpc.pb.goGenConfig生成配置结构体config.goGenSvc生成依赖注入容器servicecontext.goGenLogic生成业务逻辑骨架*logic.goGenServer生成服务端注册代码*server.goGenMain生成入口main文件服务名.goGenCall当--clienttrue默认时生成 RPC 客户端封装*client/*.go。其中GenPb执行的真实命令正是由 cli/zrpc.go 的ZRPC入口拼接出的 protoc 命令——这就是protoc 参数原样透传与gRPC 桩代码由 protoc 生成、zRPC 业务代码由 goctl 生成的双层架构分工。示例仓库10 个覆盖全部生成场景的完整范例仓库的 tools/goctl/rpc/example/ 目录收录了 10 个可直接运行的完整示例每个示例都包含.proto源文件以及英/中/韩三语说明文档#示例覆盖场景01基础服务单一服务无 import02同目录 import从同一目录 import03子目录 import从子目录 import04传递性 importA → B → C 依赖链05多服务--multiple模式06well-known types消息中使用 Timestamp 等07外部 proto同包外部 proto相同 go_package08外部 proto异包外部 proto不同 go_package09well-known types 作参数Empty/Timestamp 作为 RPC 参数10流式服务端/客户端/双向流式例如 01-basic/greeter.proto 展示了一个最基础的 proto 定义包含syntax、package、go_package声明一对HelloReq/HelloReply消息以及一个SayHelloRPC 方法。以它作为起点逐步对照 0210 号示例即可覆盖从 import 到多服务再到流式的全部生产级使用模式。小结goctl rpc将手写 gRPC 样板代码这一繁琐环节完全自动化编写.proto定义 → 执行为一条goctl rpc protoc命令 → 得到完整可运行的 zRPC 服务工程只需在internal/logic中填充业务逻辑。多服务、跨目录 import、流式与 well-known types 等高级特性均有官方示例佐证配合源码中的生成管线与 import 解析实现开发者既能快速上手也能按需深入定制。赞分享后端RPC框架Web框架微服务API网关服务注册发现代码生成【免费下载链接】go-zeroA cloud-native Go microservices framework with cli tool for productivity.项目地址https://gitcode.com/GitHub_Trending/go/go-zero点击查看免费下载相关推荐goctl rpc 使用指南从 .proto 文件一键生成 go-zero zRPC 服务代码goctl rpc 使用指南从 .proto 文件一键生成 go zero zRPC 服务代码 goctl rpc 是 go zero 脚手架 goctl 的后端RPC框架Web框架微服务API网关服务注册发现代码生成go-zero goctl rpc 实战指南基于 .proto 文件一键生成完整 zRPC 服务代码go zero goctl rpc 实战指南基于 .proto 文件一键生成完整 zRPC 服务代码 goctl rpc 是 go zero 微服务框架脚手架后端RPC框架Web框架微服务API网关服务注册发现代码生成go-zero goctl 多服务模式实战goctl rpc protoc --multiple 单 proto 生成多 RPC 服务全指南go zero goctl 多服务模式实战 goctl rpc protoc multiple 单 proto 生成多 RPC 服务全指南 本指南以 go z后端RPC框架Web框架微服务API网关服务注册发现代码生成上一篇iptvnator 中 Shaka Player 结构化诊断版本锁定的证据边界设计与实现下一篇Node.js 11.7.0 (Current) 发布解析Brotli 压缩落地、worker_threads 去掉实验性标志与 npm 6.5.0 升级创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表