本文轉自本文轉載自:http://roclinux.cn/?p=3316
在英語裏,thrift是個名詞,表示的是“節儉、節約”,給個例句會印象更深些:
Farmers know a lot about value and thrift。(譯:農場主深諳價值與節儉之道。)
然而,這篇文章並非是一篇英語學習教程,而是要和大家介紹計算機技術裏一款著名的通信框架 – thrift框架。
好,現在有請thrift登場。
【thrift是什麼】
thrift的全名叫做Apache thrift,是一款軟件開發RPC框架,可以很高效地實現跨語言的RPC服務。
如果你還不瞭解RPC是什麼,趕快看看這裏。
如果想參觀參觀thrift的官方網站,請點擊這裏。
【thrift生於何地】
thrift最初生於Facebook,並茁壯成長,在2007年由Facebook正式開源出來,2008年由Apache軟件基金會開始負責項目孵化直至今日。
【還有哪些RPC框架】
protobuf、Avro、MessagePack等,如果你有興趣,可以搜索一下他們,也有利於你更好的瞭解RPC這個領域的發展情況。
【下載thrift】
目前的最新版本是thrift-0.9.1
【安裝thrift】
首先建議你安裝如下這些軟件包:
automake libtool flex bison pkgconfig gcc-c++ boost-devel \ libevent-devel zlib-devel python-devel ruby-devel
然後從官網下載thrift源碼包,並進行編譯鏈接:
./configure –-prefix=/your/program/path/ --enable-libtool-lock make make install
安裝完成後,你會看到thrift其實包含了三部分:一個bin程序、一坨頭文件和若干庫文件
#小知識 ls使用-F選項的話,文件列表中會用符號表示文件屬性,
#如*表示可執行文件,@表示軟連接,/表示文件夾
[rocrocket@li218-69 thrift]$ ls -1F bin
thrift*
[rocrocket@li218-69 thrift]$ ls -1F lib
libthrift-0.9.1.so*
libthrift.a
libthrift.la*
libthriftnb-0.9.1.so*
libthriftnb.a
libthriftnb.la*
libthriftnb.so@
libthrift.so@
libthriftz-0.9.1.so*
libthriftz.a
libthriftz.la*
libthriftz.so@
pkgconfig/
[rocrocket@li218-69 thrift]$ ls -1F include/thrift/
async/
concurrency/
config.h
cxxfunctional.h
processor/
protocol/
qt/
server/
TApplicationException.h
TDispatchProcessor.h
thrift-config.h
Thrift.h
TLogging.h
TProcessor.h
transport/
TReflectionLocal.h
【爲什麼需要thrift】
如果你之前沒有接觸過RPC框架的話,可能理解起來會比較困難。爲了照顧這些新用戶的感受,我嘗試着用一種好理解的思路來解釋:
研發工程師小吳接到了一個新任務,給“托福考試成績數據庫”增加一個“成績查詢”的功能,客戶端提供“用戶ID”向服務器端發起查詢請求,服務器端接到查詢請求後從數據庫中取回此用戶ID對應的姓名和成績,並返回給客戶端。
就是這樣一個簡單的Client-Server通信過程,其實就形成了一個典型的RPC場景。服務器端提供“成績查詢服務”,客戶端會通過約定的方法來查詢成績。
小吳設計的方法調用和數據傳輸是這樣的:
thrift example
通過上圖可以看到,服務器端處於監聽狀態(等待請求的到來),客戶端發起一個名爲Search的動作,參數是用戶ID,而這個動作的返回是一個結構體struct UserGradeInfo,其中包含了用戶的名字(UserName)和用戶的成績(UserGrade)。
設計做完了,小吳要開始編碼了。如果按照“手工作坊”的思路,小吳至少需要完成如下幾個方面:
(1)“客戶端向服務器端發送數據”的代碼
(2)“客戶端接收服務器端查詢結果”的代碼
(3)“服務器端接收客戶端數據”的代碼
(4)“服務器端向客戶端發送查詢結果”的代碼
(5)如果客戶端會大批量發起查詢,那可能還需要考慮改成多線程模型或異步模型
(6)而且還有可能因爲某種原因,要求客戶端和服務器端使用不同的語言進行開發
照此思路,小吳至少要3周時間來開發和自測。(時間很長,對吧)
但,自從thrift出現後(更準確的說,是自從RPC開發框架出現後),上述工作量被大大簡化了。我們只要調用一個thrift工具就可以自動生成上述的所有代碼,即便服務器端和客戶端使用不同的語言,thrift也照樣支持。
至此,我相信你應該大概理解thrift能幫我們做什麼了吧。
【thrift到底怎麼用】
依然拿上面的“成績數據庫”的例子來說,thrift的使用可以被分爲四步:
第1步: 明確要交互的數據格式(如上例中的UserGradeInfo)和具體的方法(如上例中的Search),定義出thrift接口描述文件(英文叫做Inteface Description File);
第2步: 調用thrift工具,依據thrift接口文件,生成RPC代碼;
第3步: 你的服務器端程序引用thrift生成的RPC代碼,並實現其中的Search動作的邏輯,然後啓動監聽,等待客戶端發來請求。
第4步: 客戶端同樣引入並調用RPC代碼來與服務器端通信;
(如果你覺得這樣描述太空虛,別急,稍後會有完整的例子)
【thrift接口描述文件怎麼編寫】
如果你是學院派,那麼我推薦你研究thrift IDL(Interface Definition Language)規範,在這裏。雖然有些晦澀,但你可以從中瞭解到一個接口文件可以如何來寫。
在編寫接口文件時,需要對你要傳輸的數據設定數據類型,比如UserName是字符串型,UserGrade是整型等。因爲thrift是支持衆多開發語言的,所以thrift提供了一套自己的數據類型編寫規範,只有用這套獨立於任何語言的類型規範來編寫接口文件,thrift才能把它轉換成你指定的那種開發語言的代碼。
thrift中的類型包括基礎類型、結構、容器、異常、服務等幾個部分。(官網中有專門介紹數據類型的頁面,在這裏)
【類型 之 基礎類型】
基礎類型,其實非常簡單和明確:
(1)bool:布爾類型(true或false)
(2)byte:8位有符號整數
(3)i16:16位有符號整數
(4)i32:32位有符號整數
(5)i64:64位有符號整數
(6)double:64位浮點數
(7)string:文本字符串,使用UTF-8編碼
(有些細心的同學會詢問“爲什麼不支持無符號整數類型呢?”,這是因爲在很多開發語言中並沒有原生的無符號整型。)
【類型 之 容器】
thrift容器包括了各種語言中最常用的容器,共三種:
(1)list容器:一個元素可重複的有序列表。會被轉換成C++中的vector,Java中的ArrayList,腳本語言中的數組等。
(2)set容器:一個元素不可重複的無序集合。會轉換成C++中的set,Java中的HashSet、Python中的Set等。(熟悉PHP的同學可能會問“PHP並不支持set類型,怎麼辦”,在PHP語言中,thrift會將set容器轉換成List。)
(3)map容器:一個含有多個key:value鍵值對的結構。會被轉換成C++中的map,Java中的HashMap,PHP中的關聯數組,Python/Ruby中的dictionary等。
對於上述三種容器,其元素的類型原則上可以是任何一種thrift類型。但是值得注意的是,map的key類型需要是基礎類型,因爲很多開發語言並不支持map的key類型爲複雜數據類型。
【類型 之 結構體】
結構體類型,在形式上和C/C++中的結構體類型非常相似,就是一坨類型的組合,比如上文圖中的UserGradeInfo便是一個thrift結構體類型。
thrift接口文件中的結構體類型,都會被轉換成一個獨立的類(Class)。類的屬性便是結構體中的各個類型,而類的方法便是對這些類型進行處理的相關函數。
我們來看一個結構體定義的例子:
struct UserGradeInfo {
1: required string UserName = "Anonymous";
2: required i16 UserGrade = 0;
}
可以看到,結構體中每一個域都有一個正整數標識符,這個標識符並不要求連續,但一旦定義,不建議再進行修改。
另外,每個域前都會有required或optional的限定,前者表示是必填域,後者則表示是可選域。域是可以有默認值的,比如上例中的“Anonymous”和0。
(1)如果一個域設置了required,但是在實際構造結構體時又沒有給這個域賦值,那麼thrift會認爲這是一個異常。
(2)如果一個域設置爲optional且在構造結構體時沒有給這個域賦值,那麼在使用這個結構體時,就會忽略掉這個optional的域。
【類型 之 異常】
除了使用exception來替代struct以外,“異常”這個類型,在語法上和剛纔介紹過的結構體的用法是完全一致的。但是從語義上講,exception和struct卻大相徑庭。exception是在遠程調用發生異常時用來拋出異常用的。
【類型 之 服務】
服務的定義,與面向對象技術中定義一個接口很類似,而這些接口其實就是純虛函數。thrift編譯工具會根據服務的定義來產生相應的方法和函數。
每個服務,都包括了若干個函數,每個函數包括了若干參數和一個返回值(返回值可以是void)。
(小技巧:返回值爲void的函數,你可以在函數名前加上oneway標識符,將此函數以異步模式執行,這樣在調用此函數後,函數會立即返回。)
對於返回void的函數,thrift仍然會確保函數返回,這樣就表示這個函數已被正確執行,且服務器端已有返回信息了。但是如果給void的函數前加上oneway,那麼此函數的返回只能表示數據已經進入傳輸層,並不能表示服務器端已經收到並返回了數據。
【我們來看一個thrift接口描述文件的例子吧】
# 例子 - thrift接口描述文件
#
# 編寫這個文件是爲了教會你如何寫thrift接口描述文件。
# 第一個你應該掌握的知識點就是.thrift文件
# 支持shell的註釋方式,那就是用#符號。
/**
* 我們首先來複習一下thrift的常用數據類型,如下所示:
*
* bool 布爾型,1個字節
* byte 有符號整數,1個字節
* i16 有符號16位整型
* i32 有符號32位整型
* i64 有符號64位整型
* double 64位浮點數值
* string 字符串類型
* binary 二進制數據類型(字節數組)
* list 單類型有序列表,允許有重複元素
* set 單類型無需集合,不允許有重複元素
* map<t1,t2> Map型(key:value)
*
- 你發現了麼,.thrift文件還支持C語言的多行註釋形式。
*/
// 不賣關子了,其實我們還支持C語言的單行註釋形式呢 _
/**
- .thrift文件可以引用其他.thrift文件,這樣就可以方便地把一些公共結構和服務囊括進來。
- 在引用其他.thrift文件時,既可以直接引用當前文件夾下的文件,也可以引用其他路徑下的
- 文件,但後者需要在thrift編譯工具編譯時加上-I選項來設定路徑。
- 如果希望訪問被包含的.thrift文件中的內容,則需要使用.thrift文件的文件名作爲前綴,
- 比如shared.SharedObject。我們在本例中引用了文件shared.thrift。
*/
include “shared.thrift”
/**
-
Thrift支持對.thrift文件中的類型設定namespace,這樣可以有效避免名字衝突。
-
這種機制在C++中也叫做namespace,而在Java中叫做Package。
-
thrift支持針對不同的語言設置不同的namespace,比如下面的例子。
-
thrift會在生成不同語言代碼時,進行相應的設置。
*/
namespace cpp tutorial
namespace go tutorial
namespace java tutorial
namespace php tutorial
namespace perl tutorial
/**
- thrift還可以使用typedef來給類型起別名。
*/
typedef i32 MyInteger
/**
- Thrift也支持定義常量。
- 對於結構複雜的常量,支持使用JSON形式來表示。
*/
const i32 MY_NUM = 9853
const map<string,string> MY_MAP = {‘hello’:‘world’, ‘goodnight’:‘moon’}
/**
- 你還可以定義枚舉類型, 其被指定爲32位整型。域的值是可以自定義的,而且
- 當不提供域的值時,默認會從1開始編號並遞增。
*/
enum Operation {
ADD = 1,
SUBTRACT = 2,
MULTIPLY = 3,
DIVIDE = 4
}
/**
- 結構體則是一個複雜的數據類型。它由多個域組成,每個域會對應一個整數標識符,
- 每一行的格式爲:一個冒號,一個類型,一個域名稱和一個(非必填的)默認值。
- 每個域都可以設置爲optional或required來表示是否爲必填域,以便thrift決定是否
- 在數據傳輸時要包含這個域。不指定時,默認爲required。
*/
struct Work {
1: i32 num1 = 0,
2: i32 num2,
3: Operation op,
4: optional string comment,
}
/**
- 在語法上,異常的定義方式和結構體是完全一樣的。在發生問題時,可以拋出異常。
*/
exception InvalidOperation {
1: i32 what,
2: string why
}
/**
- 啊哈,我們現在到了最Cool的環節,即定義服務。
- (一個服務可以使用extends來繼承另一個服務。)
*/
service Calculator extends shared.SharedService {
/**
- 服務中方法的定義非常類似於C語言的語法。它會包括一個返回值,
- 一個參數列表以及一個可以拋出的異常列表(可選)
- 可以提前告訴大家的是,定義參數列表的方法、定義異常列表的方法,
- 和定義結構體的方法都是相似的,可以從下面的例子中看出。
- 除了最後一個方法,其他的方法最後都要有一個逗號,大家可不要忽略這個細節。
*/
void ping(),
i32 add(1:i32 num1, 2:i32 num2),
/**
- 在異常列表前,需要加throws關鍵字。
*/
i32 calculate(1:i32 logid, 2:Work w) throws (1:InvalidOperation ouch),
/**
- 如下的這個方法有一個oneway修飾符,還記得他的作用麼
- 這表示這個方法在調用後會立即返回,不會等待遠端的回覆。
- 要注意的是,oneway只能修飾void返回類型。
- oneway在英語裏就是“單向”的意思,還是很形象滴。
*/
oneway void zip()
}
/**
- 在你使用thrift編譯工具編譯此文件後,
- 會在當前目錄產生一個“gen-<你選擇的開發語言>”
- 文件夾,比如你選擇的是C++語言,則會產生gen-cpp文件夾,
- 裏面放着的便是thrift幫你生成好的代碼,
- 代碼並不那麼晦澀,你可以打開看一看。
*/
【使用thrift編譯工具】
在我們編寫好thrift接口描述文件之後,thrift編譯工具就要派上用場了,它的作用就是根據thrift接口描述文件來生成相應開發語言的RPC代碼,以便用戶可以在自己的程序中調用。
thrift編譯工具的名稱就是thrift,其最常見的使用方式是這樣的:
thrift --gen ${開發語言} ${thrift接口描述文件}
# 運行了上述命令之後,就會在當前文件夾下生成一個以“gen-${開發語言}”命名的文件夾,
# 裏面便是自動生成的代碼。
【thrift會自動生成哪些代碼呢】
在編譯之後,thrift會生成這些文件:(我們以mytime.thrift爲例)
$ cd gen-cpp
$ ls -1 mytime_types.*
mytime_types.cpp
mytime_types.h
# 和數據類型有關的內容,會命名爲
# {thrift_file_name}_types.cpp。
# 比如你使用typedef定義了類型別名,
# 或者你定義了一個struct類型,都會在這兩個文件中記錄。
# 對於struct類型,有必要多說一下,thrift會針對每一個struct類型
# 生成一個對應的類,類中會包括一個構造函數、一個析構函數、
# 域變量定義、用於設置域值的__set_XXX()方法、
# 重載比較符(==,!=,<)、設定讀寫此結構體的方法read/write,
# 以及一個用於表示域是否設置了值的_${struct name}__isset結構體。
# 另外,還會有一個獨立定義的swap方法用來進行兩個結構體的值交換。
$ ls -1 mytime_constants.*
mytime_constants.cpp
mytime_constants.h
# 和常量有關的內容,會命名爲
# {thrift_file_name}_constants.cpp。
# 在.h頭文件中會有一個${thrift_file_name}Constants類,
# 其中會包括一個顯式的構造函數,以及常量的域。
# 而在cpp文件中則會在相應的構造函數中對這個常量進行賦值。
$ ls -1 myservice*
myservice.cpp
myservice.h
myservice_server.skeleton.cpp
# 針對每一個service會產生一套對應的文件,命名爲
# {service_name}.h/KaTeX parse error: Expected 'EOF', got '#' at position 71: …"hljs-comment">#̲ 在{service_name}.h中會看到有若干個類,他們都是以服務名作爲前綴的,
# 其中包括{service_name}IfFactory、
# {service_name}Null、
# {service_name}Processor、
# {service_name}Multiface。
# 另外,thrift還會針對服務中的每一個具體的方法分別產生四個對應的類,即
# KaTeX parse error: Expected group after '_' at position 15: {service_name}_̲{method}_args、KaTeX parse error: Expected group after '_' at position 15: {service_name}_̲{method}_pargs、
# KaTeX parse error: Expected group after '_' at position 15: {service_name}_̲{method}_result、KaTeX parse error: Expected group after '_' at position 15: {service_name}_̲{method}_presult。
# 另外,${service_name}_server.skeleton.cpp是一個server的模板例子。
【一起用thrift來做個項目!】
從我的學習經驗來看,框架的學習路線是“瞭解應用場景 -> 瞭解用法 -> 看例子 -> 深入用戶 -> 自己寫例子”。我相信,如果你能和我一起走完這個例子,一定會消除對thrift的恐懼,愛上這款RPC框架的。
我們的例子很簡單,就是一個“時間問答”機器人,英文叫做WhatTime,客戶會向服務器端詢問現在幾點啦,服務器端會把現在的時間回答給客戶端。就像這樣:
客戶端:請問,現在幾點啦?
服務器端:現在是上午10點01分。
我們會在服務器端使用C++來實現,而在客戶端會使用C++語言來實現一版,還會使用最近很流行的Go語言實現一版。(Go語言可是未來可能撼動IT界的語言之一哦)
thrift接口描述文件WhatTime.thrift:
namespace cpp roctime
service TimeService {
i32 TellMeTime()
}
需要經過thrift編譯工具編譯:
$ thrift --gen cpp WhatTime.thrift
$ ls -1F
gen-cpp/
WhatTime.thrift
$ cd gen-cpp/
$ ls -1
TimeService.cpp
TimeService.h
TimeService_server.skeleton.cpp
WhatTime_constants.cpp
WhatTime_constants.h
WhatTime_types.cpp
WhatTime_types.h
然後,我們把server的樣例文件重命名一下:
$ mv TimeService_server.skeleton.cpp server.cpp
我們將server.cpp中的TellMeTime方法做一些修改,加入報告時間的邏輯:
int32_t TellMeTime() {
// Your implementation goes here
time_t now_time = time(NULL);
return now_time;
}
好了,server.cpp完工,我們對server.cpp進行編譯鏈接:
g++ -I /home/roc/program/thrift/include -c TimeService.cpp
g++ -I /home/roc/program/thrift/include -c WhatTime_constants.cpp
g++ -I /home/roc/program/thrift/include -c WhatTime_types.cpp
g++ -I /home/roc/program/thrift/include -c server.cpp
g++ -L /home/roc/program/thrift/lib/ TimeService.o WhatTime_constants.o WhatTime_types.o server.o -o server -lthrift
如果提示找不到thrift動態鏈接庫,那就需要把thrift的lib路徑(如/home/roc/program/thrift/lib)加入到ld.so.conf中,然後執行ldconfig命令在重新將動態鏈接庫裝載到cache中。
然後就可以直接運行./server了,可以看到9090端口打開,已經開始服務了。
下面,我們繼續編寫客戶端的代碼。thrift並沒有給出客戶端的代碼樣例,所以需要自己來開發。
#include "TimeService.h"
#include <thrift/transport/TSocket.h>
#include <thrift/transport/TBufferTransports.h>
#include <thrift/protocol/TBinaryProtocol.h>
using namespace std;
using namespace apache::thrift;
using namespace apache::thrift::protocol;
using namespace apache::thrift::transport;
using namespace roctime;
int main(int argc, char *argv[]) {
boost::shared_ptr<TSocket>socket(new TSocket(“localhost”, 9090));
boost::shared_ptr<TTransport> transport(new TBufferedTransport(socket));
boost::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
time_t mytime = 0;
TimeServiceClient client(protocol);
transport->open();
mytime = client.TellMeTime();
cout << "Now is " << ctime(&mytime) << endl;
transport->close();
return 0;
}
開發完成後,我們對client進行編譯鏈接:
g++ -I /home/roc/program/thrift/include -c TimeService.cpp
g++ -I /home/roc/program/thrift/include -c WhatTime_constants.cpp
g++ -I /home/roc/program/thrift/include -c WhatTime_types.cpp
g++ -I /home/roc/program/thrift/include -c client.cpp
g++ -L /home/roc/program/thrift/lib/ TimeService.o WhatTime_constants.o WhatTime_types.o client.o -o client -lthrift
好了,服務器端程序server和客戶端程序client都生成好了,可以試着運行這個例子:
在一個終端運行服務器端程序:
$ ./server
在另一個終端打開客戶端程序:
$ ./client
Now is Fri Nov 1 12:14:06 2013
順利的話,你應該可以看到運行server的終端窗口會輸出“Now is Fri Nov 1 12:14:06 2013”啦!RPC通信成功了!
至此,C++版本的客戶端和服務器端都已經實現了。是不是並沒有那麼的難呢!下面,我們來看看Go語言的客戶端如何實現。
【Go語言版客戶端】
首先通過thrift來生成go的代碼:
$ thrift -gen go WhatTime.thrift
會生成gen-go文件夾,進入其中,可以看到這裏面有什麼東東:
$ cd gen-go/
$ ls -1F
WhatTime/
在gen-go文件夾中,我們作如下的操作:
#有人會問爲什麼要搞個src文件夾呢,稍後你就會知道答案
$ mkdir src
#將thrift自動生成的WhatTime文件夾移動到src中
$ mv WhatTime src/
#將當初源碼安裝thrift時的文件夾(也就是tar.gz解包後的文件夾)中的lib/go/thrift拷貝到src中。
#拷貝過來的thrift文件夾中全都是.go文件,這些便是thrift支持go語言的庫文件,用於我們稍後編譯鏈接所用。
$ cp -r /path/to/source/thrift/lib/go/thrift/ .
#都完成後,我們看看gen-go/src文件夾中的目錄結構
$ ls -1F
thrift/
WhatTime/
#設置GOPATH全局變量,以便Go語言能查找到所需的包
#當我們設置了GOPATH之後,Go語言會默認在KaTeX parse error: Expected 'EOF', got '#' at position 21: …H/src下來查找相應的包,
#̲這下你應該明白爲什麼當初要創建…GOPATH:/path/to/gen-go"
#除此之外,你還要確保Go語言已經正確安裝,且PATH和GOROOT也已正確設置。
export PATH="/path/to/go_dir/bin:${PATH}"
export GOROOT=""/path/to/go_dir"
下一步,我們需要對$GOPATH/src/WhatTime中的constants.go、time_service.go和ttypes.go三個文件做一下小的修改:
我們將import區域中的 "git.apache.org/thrift.git/lib/go/thrift" 修改爲 "thrift"
作如上修改的原因,其一是我們已經在本地準備好了支持thrift的go語言包,
其二是因爲這樣可以避免在無法連接到互聯網的情況下,程序編譯失效。
說實話,Go語言的準備工作確實有些繁瑣,希望你還有耐心看最關鍵的內容,那就是編寫client.go的代碼!
我們在src的同級目錄中來編寫,client.go的代碼如下:
package main
import (
“WhatTime”
“fmt”
“thrift”
“time”
)
func handleClient(client *WhatTime.TimeServiceClient) (err error) {
t, _ := client.TellMeTime()
fmt.Println(time.Unix(<span class="hljs-keyword">int64</span>(t), <span class="hljs-number">0</span>).String())
<span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span>
}
func runClient(transportFactory thrift.TTransportFactory, protocolFactory thrift.TProtocolFactory, addr string) error {
<span class="hljs-keyword">var</span> transport thrift.TTransport
transport, err := thrift.NewTSocket(addr)
<span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
fmt.Println(<span class="hljs-string">"Error opening socket:"</span>, err)
<span class="hljs-keyword">return</span> err
}
transport = transportFactory.GetTransport(transport)
<span class="hljs-keyword">defer</span> transport.Close()
<span class="hljs-keyword">if</span> err := transport.Open(); err != <span class="hljs-literal">nil</span> {
<span class="hljs-keyword">return</span> err
}
<span class="hljs-keyword">return</span> handleClient(WhatTime.NewTimeServiceClientFactory(transport, protocolFactory))
}
func main() {
<span class="hljs-keyword">var</span> protocolFactory thrift.TProtocolFactory
protocolFactory = thrift.NewTBinaryProtocolFactoryDefault()
<span class="hljs-keyword">var</span> transportFactory thrift.TTransportFactory
transportFactory = thrift.NewTBufferedTransportFactory(<span class="hljs-number">1024</span>)
addr := <span class="hljs-string">"localhost:9090"</span>
<span class="hljs-keyword">if</span> err := runClient(transportFactory, protocolFactory, addr); err != <span class="hljs-literal">nil</span> {
fmt.Println(<span class="hljs-string">"error running client:"</span>, err)
}
}
然後進行編譯鏈接和運行:
$ go build client.go
$ ./client
2013-11-01 12:37:31 +0800 CST
【結語】至此,我們的Go語言版本也大功告成了!
如果你耐心地看到了這裏,說明你完成了thrift的入門。但是“紙上得來終覺淺,自己動手纔是真”。
後面還會有Thrift進階篇,敬請期待。
如果你覺得這篇文章對你有一些幫助,希望能通過捐款的方式支持Linux大棚和博主:)
謝謝!