Files
go-zero/tools/goctl/rpc/CHANGELOG-cn.md

6.6 KiB
Raw Permalink Blame History

变更日志

未发布

新功能

外部 Proto 导入支持(--proto_path / -I

新增通过 -I / --proto_path 标志导入外部目录中的 proto 文件,支持完整的传递性依赖解析。

涉及文件:

  • generator/gen.goZRpcContext 新增 ProtoPaths 字段;新增 resolveImportedProtos() 在代码生成前填充 ImportedProtos
  • generator/genpb.go — 新增 buildProtocCmd() 自动发现并追加传递性导入的 proto 文件到 protoc 命令;新增 relativeToProtoPath() 计算正确的相对路径。
  • parser/import.go — 新文件(主要新增)。实现 ResolveImports() 递归解析传递性导入,ParseImportedProtos() 提取导入 proto 的 go_package / package 元数据,BuildProtoPackageMap() 构建按 proto 包名的 O(1) 查找表。
  • parser/proto.goProto 结构体新增 ImportedProtos []ImportedProto 字段。
  • cli/cli.goRPCNew 传递 ProtoPathsZRpcContext
  • cli/zrpc.go — 将 VarStringSliceProtoPath 传递到 ZRpcContext.ProtoPaths

前后对比:

变更前 变更后
从外部目录导入 Proto 不支持,所有类型必须在同一文件中定义 使用 -I ./ext_protos 添加搜索路径
传递性导入A → B → C 仅识别直接导入 递归解析所有传递性依赖
导入 proto 的 .pb.go 生成 需手动为每个文件单独运行 protoc 自动将导入的 proto 追加到 protoc 命令
Proto 搜索路径 仅源文件所在目录 支持多个 -I 路径,与 protoc 一致

行为说明:

  • 递归遍历 proto 文件中的所有 import 声明,跳过 google/* 知名类型。
  • 在每个 -I 目录中搜索被导入的文件,未找到的系统级 proto 静默跳过。
  • 将发现的 proto 文件追加到 protoc 命令,使其 .pb.go 文件与主 proto 一同生成。

跨包类型解析

当导入的 proto 与主 proto 具有不同go_packagegoctl 现在能够自动在 server、logic 和 client 代码中生成正确的 Go 导入路径和限定类型引用。

涉及文件:

  • generator/typeref.go — 新文件,核心类型解析引擎:
    • resolveRPCTypeRef() — 将 proto RPC 类型简单类型、同包点号类型、跨包点号类型、Google WKT解析为带正确导入路径的 Go 类型引用。
    • resolveCallTypeRef() — 客户端代码生成变体,支持类型别名。
    • googleWKTTable — 全部 16 种 Google 知名类型到 Go 等价类型的映射表。
  • generator/genserver.gogenFunctions() 调用 resolveRPCTypeRef() 解析请求/响应类型并收集额外导入路径。
  • generator/genlogic.gogenLogicFunction() 使用 resolveRPCTypeRef();新增 addLogicImports() 按需添加主 pb 导入和跨包导入。
  • generator/gencall.gogenFunction()getInterfaceFuncs() 使用 resolveCallTypeRef() 处理类型别名和额外导入;新增 buildExtraImportLines() 辅助函数。
  • generator/call.tpl — 新增 {{.extraImports}} 占位符用于跨包导入行。

前后对比:

Proto 类型 变更前 变更后
GetReq(同文件) pb.GetReq pb.GetReq(无变化)
ext.ExtReq(相同 go_package 报错:"request type must defined in" pb.ExtReq — 合并到主包
common.TypesReq(不同 go_package 报错:"request type must defined in" common.TypesReq + 自动生成 import "example.com/demo/pb/common"
google.protobuf.Empty 报错:"request type must defined in" emptypb.Empty + 自动生成导入

行为说明:

  • 简单类型(如 GetReq)解析为 pb.GetReq,无额外导入。
  • 同包点号类型(如 ext.ExtReq,其中 ext 与主 proto 有相同的 go_package)解析为 pb.ExtReq
  • 跨包点号类型(如 common.TypesReq,其中 common 有不同的 go_package)解析为 common.TypesReq,并自动添加正确的 Go 导入路径。

Google 知名类型作为 RPC 参数

Google protobuf 知名类型现在可以直接用作 RPC 的请求/响应类型(而不仅仅是消息字段)。

涉及文件:

  • generator/typeref.goresolveGoogleWKT() + googleWKTTable 处理所有标准类型。

前后对比:

Proto 类型 变更前(作为 RPC 参数) 变更后(作为 RPC 参数)
google.protobuf.Empty 报错 emptypb.Empty
google.protobuf.Timestamp 报错 timestamppb.Timestamp
google.protobuf.Duration 报错 durationpb.Duration
google.protobuf.Any 报错 anypb.Any
google.protobuf.Struct 报错 structpb.Struct
google.protobuf.FieldMask 报错 fieldmaskpb.FieldMask
google.protobuf.*Value 报错 wrapperspb.*Value

注:这些类型此前已可用作消息字段。本次变更使其可直接用作 RPC 请求/响应类型

完整类型映射表:

Proto 类型 Go 类型
google.protobuf.Empty emptypb.Empty
google.protobuf.Timestamp timestamppb.Timestamp
google.protobuf.Duration durationpb.Duration
google.protobuf.Any anypb.Any
google.protobuf.Struct structpb.Struct
google.protobuf.Value structpb.Value
google.protobuf.ListValue structpb.ListValue
google.protobuf.FieldMask fieldmaskpb.FieldMask
google.protobuf.*Value(包装类型) wrapperspb.*Value

不兼容变更

RPC 定义中允许使用点号类型名

此前 goctl 会拒绝 RPC 请求/响应类型中包含点号的情况(如 base.Req),要求所有类型必须定义在同一个 proto 文件中。此限制已移除。

前后对比:

Proto 定义 变更前 变更后
rpc Fetch(base.Req) returns (base.Reply) 解析错误:"request type must defined in xxx.proto" 解析成功,base.Req 通过导入的 proto 解析
rpc Ping(google.protobuf.Empty) returns (Reply) 解析错误:"request type must defined in xxx.proto" 解析成功,解析为 emptypb.Empty

涉及文件:

  • parser/service.go — 移除了拒绝点号类型名的验证循环(原错误信息为 "request type must defined in" / "returns type must defined in")。
  • parser/parser_test.goTestDefaultProtoParseCaseInvalidRequestTypeTestDefaultProtoParseCaseInvalidResponseType 重命名并更新,验证点号类型现在可以正常解析。