Kitex 代碼生成工具

2022-04-27 10:13 更新

代碼生成工具

kitex 是 Kitex 框架提供的用于生成代碼的一個(gè)命令行工具。目前,kitex 支持 thrift 和 protobuf 的 IDL,并支持生成一個(gè)服務(wù)端項(xiàng)目的骨架。

安裝

go install github.com/cloudwego/kitex/tool/cmd/kitex

用 go 命令來安裝是最簡(jiǎn)單的,你也可以選擇自己從源碼構(gòu)建和安裝。要查看 kitex 的安裝位置,可以用:

go list -f {{.Target}} github.com/cloudwego/kitex/tool/cmd/kitex

注意,由于 kitex 會(huì)為自身的二進(jìn)制文件創(chuàng)建軟鏈接,因此請(qǐng)確保 kitex 的安裝路徑具有可寫權(quán)限。

依賴與運(yùn)行模式

底層編譯器

要使用 thrift 或 protobuf 的 IDL 生成代碼,需要安裝相應(yīng)的編譯器:thriftgo 或 protoc。

kitex 生成的代碼里,一部分是底層的編譯器生成的(通常是關(guān)于 IDL 里定義的結(jié)構(gòu)體的編解碼邏輯),另一部分是用于連接 Kitex 框架與生成代碼并提供給終端用戶良好界面的膠水代碼。

從執(zhí)行流上來說,當(dāng) kitex 被要求來給一個(gè) thrift IDL 生成代碼時(shí),kitex 會(huì)調(diào)用 thriftgo 來生成結(jié)構(gòu)體編解碼代碼,并將自身作為 thriftgo 的一個(gè)插件(名為 thrift-gen-kitex)來執(zhí)行來生成膠水代碼。當(dāng)用于 protobuf IDL 時(shí)亦是如此。

而以哪個(gè)名字運(yùn)行,決定了 kitex 的執(zhí)行模式是命令行入口還是一個(gè)插件(thriftgo 的或 protoc 的),所以 kitex 的安裝目錄需要具備可寫權(quán)限,用于 kitex 建立必要的軟鏈接以區(qū)分不同的執(zhí)行模式。

{#content}gt; kitex IDL
    |
    | thrift-IDL
    |---------> thriftgo --gen go:... -plugin=... -out ... IDL
    |        |
    |        -----> thrift-gen-kitex (symbol link to kitex)
    |
    | protobuf-IDL
    ----------> protoc --kitex_out=... --kitex_opt=... IDL
             |
             -----> protoc-gen-kitex (symbol link to kitex)

庫依賴

kitex 生成的代碼會(huì)依賴相應(yīng)的 Go 語言代碼庫:

  • 對(duì)于 thrift IDL,是 ?github.com/apache/thrift v0.13.0 ?
  • 對(duì)于 protobuf IDL,是 ?google.golang.org/protobuf v1.26.0?

要注意的一個(gè)地方是,?github.com/apache/thrift/lib/go/thrift? 的 ?v0.14.0? 版本開始提供的 API 和之前的版本是不兼容的,如果在更新依賴的時(shí)候給 ?go get? 命令增加了 ?-u? 選項(xiàng),會(huì)導(dǎo)致該庫更新到不兼容的版本造成編譯失敗。你可以通過額外執(zhí)行一個(gè)命令來指定正確的版本:

go get github.com/apache/thrift@v0.13.0
    

或用 ?replace ?指令強(qiáng)制固定該版本:

go mod edit -replace github.com/apache/thrift=github.com/apache/thrift@v0.13.0

使用 protobuf IDL 的注意事項(xiàng)

kitex 僅支持 protocol buffers 的 proto3 版本的語法。

IDL 里的 ?go_package? 是必需的,其值可以是一個(gè)用點(diǎn)(?.?)或斜線(?/?)分隔的包名序列,決定了生成的 import path 的后綴。例如

option go_package = "hello.world"; // or hello/world

生成的 import path 會(huì)是 ?${當(dāng)前目錄的 import path}/kitex_gen/hello/world?。

使用

基礎(chǔ)使用 

語法:?kitex [options] IDL?

生成客戶端代碼

kitex path_to_your_idl.thrift

執(zhí)行后在當(dāng)前目錄下會(huì)生成一個(gè)名為 kitex_gen 目錄,其中包含了 IDL 定義的數(shù)據(jù)結(jié)構(gòu),以及與 IDL 里定義的 service 相對(duì)應(yīng)的 ?*service? 包,提供了創(chuàng)建這些 service 的 client API。

生成服務(wù)端代碼

kitex -service service_name path_to_your_idl.thrift

執(zhí)行后在當(dāng)前目錄下會(huì)生成一個(gè)名為 kitex_gen 目錄,同時(shí)包含一些用于創(chuàng)建和運(yùn)行一個(gè)服務(wù)的腳手架代碼。

生成代碼的結(jié)構(gòu)

假設(shè)我們有兩個(gè) thrift IDL 文件,demo.thrift 和 base.thrift,其中 demo.thrift 依賴了 base.thrift,并且 demo.thrift 里定義了一個(gè)名為 ?demo ?的 service 而 base 里沒有 service 定義。

那么在一個(gè)空目錄下,?kitex -service demo demo.thrift? 生成的結(jié)果如下:

.
├── build.sh                     // 服務(wù)的構(gòu)建腳本,會(huì)創(chuàng)建一個(gè)名為 output 的目錄并生成啟動(dòng)服務(wù)所需的文件到里面
├── handler.go                   // 用戶在該文件里實(shí)現(xiàn) IDL service 定義的方法
├── kitex_gen                    // IDL 內(nèi)容相關(guān)的生成代碼
│   ├── base                     // base.thrift 的生成代碼
│   │   ├── base.go              // thriftgo 的產(chǎn)物,包含 base.thrift 定義的內(nèi)容的 go 代碼
│   │   └── k-base.go            // kitex 在 thriftgo 的產(chǎn)物之外生成的代碼
│   └── demo                     // demo.thrift 的生成代碼
│       ├── demo.go              // thriftgo 的產(chǎn)物,包含 demo.thrift 定義的內(nèi)容的 go 代碼
│       ├── k-demo.go            // kitex 在 thriftgo 的產(chǎn)物之外生成的代碼
│       └── demoservice          // kitex 為 demo.thrift 里定義的 demo service 生成的代碼
│           ├── demoservice.go   // 提供了 client.go 和 server.go 共用的一些定義
│           ├── client.go        // 提供了 NewClient API
│           └── server.go        // 提供了 NewServer API
├── main.go                      // 程序入口
└── script                       // 構(gòu)建腳本
    └── bootstrap.sh             // 服務(wù)的啟動(dòng)腳本,會(huì)被 build.sh 拷貝至 output 下

如果不指定 ?-service? 參數(shù),那么生成的只有 kitex_gen 目錄。

選項(xiàng) 

本文描述的選項(xiàng)可能會(huì)過時(shí),可以用 ?kitex -h? 或 ?kitex --help? 來查看 kitex 的所有可用的選項(xiàng)。

-service service_name

使用該選項(xiàng)時(shí),kitex 會(huì)生成構(gòu)建一個(gè)服務(wù)的腳手架代碼,參數(shù) ?service_name ?給出啟動(dòng)時(shí)服務(wù)自身的名字,通常其值取決于使用 Kitex 框架時(shí)搭配的服務(wù)注冊(cè)和服務(wù)發(fā)現(xiàn)功能。

-module module_name

該參數(shù)用于指定生成代碼所屬的 Go 模塊,會(huì)影響生成代碼里的 import path。

  1. 如果當(dāng)前目錄是在 ?$GOPATH/src? 下的一個(gè)目錄,那么可以不指定該參數(shù);kitex 會(huì)使用 ?$GOPATH/src? 開始的相對(duì)路徑作為 import path 前綴。例如,在 ?$GOPATH/src/example.com/hello/world? 下執(zhí)行 kitex,那么 ?kitex_gen/example_package/example_package.go? 在其他代碼代碼里的 import path 會(huì)是 ?example.com/hello/world/kitex_gen/example_package?。
  2. 如果當(dāng)前目錄不在 ?$GOPATH/src? 下,那么必須指定該參數(shù)。
  3. 如果指定了 ?-module? 參數(shù),那么 kitex 會(huì)從當(dāng)前目錄開始往上層搜索 go.mod 文件
    • 如果不存在 go.mod 文件,那么 kitex 會(huì)調(diào)用 ?go mod init? 生成 go.mod;
    • 如果存在 go.mod 文件,那么 kitex 會(huì)檢查 ?-module? 的參數(shù)和 go.mod 里的模塊名字是否一致,如果不一致則會(huì)報(bào)錯(cuò)退出;
    • 最后,go.mod 的位置及其模塊名字會(huì)決定生成代碼里的 import path。

-I path

添加一個(gè) IDL 的搜索路徑。

-type type

指明當(dāng)前使用的 IDL 類型,當(dāng)前可選的值有 thrift(默認(rèn))和 protobuf。

-v 或 -verbose

輸出更多日志。

高級(jí)選項(xiàng)

-use path

在生成服務(wù)端代碼(使用了 ?-service?)時(shí),可以用 ?-use? 選項(xiàng)來讓 kitex 不生成 kitex_gen 目錄,而使用該選項(xiàng)給出的 import path。

-combine-service 

對(duì)于 thrift IDL,kitex 在生成服務(wù)端代碼腳手架時(shí),只會(huì)針對(duì)最后一個(gè) service 生成相關(guān)的定義。如果你的 IDL 里定義了多個(gè) service 定義并且希望在一個(gè)服務(wù)里同時(shí)提供這些 service 定義的能力時(shí),可以使用 ?-combine-service? 選項(xiàng)。

該選項(xiàng)會(huì)生成一個(gè)合并了目標(biāo) IDL 文件中所有 service 方法的 ?CombineService?,并將其用作 main 包里使用的 service 定義。注意這個(gè)模式下,被合并的 service 之間不能有沖突的方法名。

-protobuf value

傳遞給 protoc 的參數(shù)。會(huì)拼接在 ?-go_out? 的參數(shù)后面??捎玫闹祬⒖?nbsp;?protoc ?的幫助文檔。

-thrift value

傳遞給 thriftgo 的參數(shù)。會(huì)拼接在 ?-g go:? 的參數(shù)后面??捎玫闹祬⒖?nbsp;?thriftgo ?的幫助文檔。kitex 默認(rèn)傳遞了 ?naming_style=golint,ignore_initialisms,gen_setter,gen_deep_equal?,可以被覆蓋。


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)