1.Thrift简介
Go 的 Thrift 是 Apache Thrift 项目为 Go 语言提供的一个跨语言的远程过程调用(RPC)框架。它的核心作用是:让你能轻松地在不同服务之间(可能用不同语言编写)进行高效、结构化的通信。
Thrift 帮你自动完成以下事情:
- 定义接口和数据结构(通过 .thrift 文件)
- 自动生成客户端和服务端代码(包括 Go 的代码)
- 序列化/反序列化数据(高效、紧凑的二进制格式)
- 网络通信封装(底层传输 + 协议解析)
核心组成部分

Thrift IDL有以下几种基本类型:
- bool:布尔型
- byte:有符号字节
- i8:8位有符号整型(低版本不支持)
- i16:16位有符号整型
- i32:32位有符号整型
- i64:64位有符号整型
- double:64位浮点型
- string:字符串(编码方式未知或二进制字符串)
注意:Thrift IDL没有无符号整数类型。因为许多编程语言中没有原生的无符号整数类型。
特殊类型
binary:表示无编码要求的byte二进制数组。因此是字节数组情况下(比如json/pb序列化后数据在thriftrpc间传输)请使用binary类型,不要使用string类型;
Golang的实现string/binary都使用string类型进行存储,string/bing/bing/binary都使用string 底层只是字节数组不保证是UTF-8编码的,可能与其他语言的行为不一致。
2.容器
Thrift 提供的容器类型是类型映射,被用作大多数编程语言中集合的原生类型。例如目前有三种容器:
- list:元素类型为 T 的有序列表,允许元素重复。Transitions to an STL vector, Java ArrayList, native arrays in scripting languages, etc.
- set:元素类型为 T 的无序集合,不允许元素重复。
- map<K,V>:键类型为 K,值类型为 V 的 map。
3.类型定义
Thrift 支持类似 C/C++ 的类型定义:
typedef i32 MyInteger
typedef Tweet Retweet
注意:typedef 定义的类型没有分号。
4.枚举类型
Thrift 提供了枚举类型。
- 编译器默认从 0 开始编号
- 可以手动指定起始值(整数)
- 不支持嵌套 enum
enum TweetType {
TWETT, // 0
RETWEET = 2, //
DM = 8ns,
REPLY
}
5.注释
Thrift 支持风格与多行注释和 C++/Java 风格的单行注释。
/*
* This is a multi-line comment.
* Just like in C.
*/
// C++/Java style single-line comments work just as well.
6.命名空间
Thrift 的命名空间类似于 C++ 的 namespace 或 Java 的 package 机制,提供了一种组织(模块)代码的方式,也可避免类型名称冲突的问题。
Thrift 支持多种语言命名空间的定义方式:
namespace cpp com.example.project
namespace java com.example.project
namespace go com.example.project
7.Include
为了方便管理,控制 URL 等,需要使用 #include 引入其他文件。Thrift 允许文件 include 其它的 thrift 文件,但不支持循环引用或递归包含。
include "tweet.thrift" ...
struct TweetSearchResult {
1: list<tweet> tweets;
}
8.常量
Thrift 中常量定义方式如下:
const i32 INT_CONST = 1234;
const map<string,string> MAP_CONST = {
"hello": "world",
"goodnight": "moon"
}
9.Struct 及 Require 说明
Structs 将字段(fields)组合在一起,每个字段有唯一的 ID、类型 type、名字 name 和一个可选的 required/optional 标记。
字段属性:
- id:每个字段有一个固定的标识符
- type:包括基本类型
- required:表示该字段必须存在(不能为 null),如果未设置会抛出异常
- optional:表示可选,可以为空
- default:用于给字段设置默认值,仅对基础类型有效
注意:optional 字段在序列化时不会被发送,而 required 字段若缺失会导致协议错误。对于复杂结构,建议使用 optional 来处理可选字段。
struct Location {
1: required double latitude,
2: required double longitude,
}
struct Tweet {
1: required i32 userId,
2: required string username,
3: required string text,
4: optional Location loc; // Struct 的定义也可以包含其他 Struct
5: optional string language = "english"; // 可设置默认值
}
10.Exception
Exception 与 struct 类似,但其用途是在远程调用过程中用于错误处理。Exception 代表函数执行失败时抛出的异常。
Service 方法中可以抛出异常,但只能由服务端抛出,客户端不能主动抛出。
service Twitter {
// A method definition looks like C code. It has a return type, arguments,
// and optionally a list of exceptions that it may throw. Note that argument
// lists and exception list are specified using the exact same syntax as
// field lists in structs.
void ping(); // 1
bool postTweet(1:Tweet tweet); // 2
TweetSearchResult search(TweetSearchQuery query); // 3
// The 'oneway' modifier indicates that the client only makes a request and does not
oneway void zip(); // 4
}
11.IDL 示例
以下为简单的 thrift idl 示例。包含 common.thrift 和 service.thrift 两个文件。
common.thrift:包含共享类型和常量定义
namespace go example.common
// typedef
typedef i32 TestInteger
// Enum
enum TestEnum {
ENUM1 = 1,
ENUM2 = 2,
ENUM3 = 3,
}
// Constant
const i32 TEST_IN_CONSTANT = 1234;
// Struct
struct TestStruct {
1: bool aBool,
2: required bool shouldReq,
3: optional bool shouldOpt,
4: list<string> aListString,
5: set<i32> aSetI32,
6: map<i32,string> aMapI32String
}
service.thrift:定义服务接口
namespace go example.service
include "common.thrift"
struct TestRequest {
1: string msg
2: common.TestStruct s
}
struct TestResponse {
1: string msg
2: common.TestStruct s
}
service TestService {
TestResponse Method1(TestRequest req)
}
12.Kitex Thrift IDL 规范
为满足性能和扩展需求,Kitex 对 IDL 格式制定了一些规范与约定:
- 方法名不能带下划线,如 get_user_info 是非法的,应改为 getUserInfo
- 参数不能为 map 或 set 类型,因为它们不支持跨语言兼容性
- 推荐使用 struct 包装多个参数,而不是传多个独立参数
- 避免使用 optional 字段,除非确实需要
- 使用统一的命名风格,如 PascalCase 或 camelCase
1712

被折叠的 条评论
为什么被折叠?



