跳到主要内容

IDL 与代码生成

IDL 为什么能作为跨语言接口契约?​

  • IDL: 接口描述语言; 用一份与语言无关的文件定义“有哪些方法、参数长什么样”,然后让工具生成各语言代码;
  • 价值: 跨语言、跨团队对齐契约; 代码生成省去手写编解码和桩代码;

如何定义可演进的 Thrift 契约?​

  • field id: 字段在二进制协议里的身份; 一旦发布,不能修改含义或复用到其他字段;
  • required: 语义上是“必须携带”; 但新增 required 字段会破坏旧调用方,维护成本高;
  • optional: 未设置时不序列化; 是新增字段最常用的选择;
  • 默认值: 接收方可能自动构造默认值; 想区分“没传”和“传了零值”时用 optional;
  • service: 一组方法的集合; 生成代码时会变成接口、Client 和 Server 桩;
namespace go api

struct GetUserRequest {
1: required i64 id
}

struct GetUserResponse {
1: optional string name
}

service UserService {
GetUserResponse GetUser(1: GetUserRequest req)
}

如何从 Thrift IDL 生成 Go 代码?​

  • -module: 生成代码使用的 Go module path; 必须与 go.mod 一致;
  • -service: 额外生成 Server scaffold; 不指定时只生成类型与 Client 桩;
  • -use: 复用另一个 module 已生成的 kitex_gen,避免重复类型;
  • -I: 增加被 include 的 IDL 搜索目录;
  • 生成结果: kitex_gen 是派生产物; 不要手工修改,业务写在 Handler;
go install github.com/cloudwego/kitex/tool/cmd/kitex@latest
go install github.com/cloudwego/thriftgo@latest
kitex --version
kitex -module example.com/user -service user api.thrift

如何生成 Protobuf 接口?​

  • Kitex: 仅支持 proto3;
  • 实践: option go_package 必须指向稳定导入路径;
  • proto: unary 默认使用 Kitex Protobuf(自定义信封,不是标准 gRPC wire);
  • IDL: 包含 stream method 时自动切换到 gRPC;
  • 实践: 没有 stream 但要求 gRPC 互通时,Client 显式配置 client.WithTransportProtocol(transport.GRPC);