go?micro微服務(wù)proto開(kāi)發(fā)安裝及使用規(guī)則
一 Protobuf介紹
Google Protocol Buffer( 簡(jiǎn)稱 Protobuf) 是 Google 公司內(nèi)部的混合語(yǔ)言數(shù)據(jù)標(biāo)準(zhǔn),目前已經(jīng)正在使用的有超過(guò) 48,162 種報(bào)文格式定義和超過(guò) 12,183 個(gè) .proto 文件。
他們用于 RPC 系統(tǒng)和持續(xù)數(shù)據(jù)存儲(chǔ)系統(tǒng)。Protocol Buffers 是一種輕便高效的結(jié)構(gòu)化數(shù)據(jù)存儲(chǔ)格式,可以用于結(jié)構(gòu)化數(shù)據(jù)串行化、或者說(shuō)序列化。
它很適合做數(shù)據(jù)存儲(chǔ)或RPC數(shù)據(jù)交換格式。可以用于即時(shí)通訊、數(shù)據(jù)存儲(chǔ)等領(lǐng)域的語(yǔ)言無(wú)關(guān)、平臺(tái)無(wú)關(guān)、可擴(kuò)展的序列化結(jié)構(gòu)數(shù)據(jù)格式
protobuf的核心內(nèi)容包括:
- 定義消息:消息的結(jié)構(gòu)體,以message標(biāo)識(shí)。
- 定義接口:接口路徑和參數(shù),以service標(biāo)識(shí)。
- 通過(guò)protobuf提供的機(jī)制,服務(wù)端與服務(wù)端之間只需要關(guān)注接口方法名(service)和參數(shù)(message)即可通信,而不需關(guān)注繁瑣的鏈路協(xié)議和字段解析,極大降低了服務(wù)端的設(shè)計(jì)開(kāi)發(fā)成本。
二 安裝Protobuf
1、下載
下載所需的安裝包,地址為:github.com/protocolbuf…

下載完成之后解壓

2、將bin目錄將入環(huán)境變量

3、查看安裝是否成功
protoc --version

三 Protobuf語(yǔ)法
1.1 基本規(guī)范
文件以.proto做為文件后綴,除結(jié)構(gòu)定義外的語(yǔ)句以分號(hào)結(jié)尾
結(jié)構(gòu)定義可以包含:message、service、enum
rpc方法定義結(jié)尾的分號(hào)可有可無(wú)
Message命名采用駝峰命名方式,字段命名采用小寫(xiě)字母加下劃線分隔方式
message SongServerRequest {
required string song_name = 1;
}
Enums類(lèi)型名采用駝峰命名方式,字段命名采用大寫(xiě)字母加下劃線分隔方式
enum Foo {
FIRST_VALUE = 1;
SECOND_VALUE = 2;
}
Service與rpc方法名統(tǒng)一采用駝峰式命名
1.2 字段規(guī)則
字段格式:限定修飾符 | 數(shù)據(jù)類(lèi)型 | 字段名稱 | = | 字段編碼值 | [字段默認(rèn)值]
限定修飾符包含 required\optional\repeated
- Required: 表示是一個(gè)必須字段,必須相對(duì)于發(fā)送方,在發(fā)送消息之前必須設(shè)置該字段的值,對(duì)于接收方,必須能夠識(shí)別該字段的意思。發(fā)送之前沒(méi)有設(shè)置required字段或者無(wú)法識(shí)別required字段都會(huì)引發(fā)編解碼異常,導(dǎo)致消息被丟棄
- Optional:表示是一個(gè)可選字段,可選對(duì)于發(fā)送方,在發(fā)送消息時(shí),可以有選擇性的設(shè)置或者不設(shè)置該字段的值。對(duì)于接收方,如果能夠識(shí)別可選字段就進(jìn)行相應(yīng)的處理,如果無(wú)法識(shí)別,則忽略該字段,消息中的其它字段正常處理。---因?yàn)閛ptional字段的特性,很多接口在升級(jí)版本中都把后來(lái)添加的字段都統(tǒng)一的設(shè)置為optional字段,這樣老的版本無(wú)需升級(jí)程序也可以正常的與新的軟件進(jìn)行通信,只不過(guò)新的字段無(wú)法識(shí)別而已,因?yàn)椴⒉皇敲總€(gè)節(jié)點(diǎn)都需要新的功能,因此可以做到按需升級(jí)和平滑過(guò)渡
- Repeated:表示該字段可以包含0~N個(gè)元素。其特性和optional一樣,但是每一次可以包含多個(gè)值??梢钥醋魇窃趥鬟f一個(gè)數(shù)組的值
數(shù)據(jù)類(lèi)型
Protobuf定義了一套基本數(shù)據(jù)類(lèi)型。幾乎都可以映射到C++\Java等語(yǔ)言的基礎(chǔ)數(shù)據(jù)類(lèi)型
| .proto | C++ | Java | Python | Go | Ruby | C# |
|---|---|---|---|---|---|---|
| double | double | double | float | float64 | Float | double |
| float | float | float | float | float32 | Float | float |
| int32 | int32 | int | int | int32 | Fixnum or Bignum | int |
| int64 | int64 | long | ing/long[3] | int64 | Bignum | long |
| uint32 | uint32 | int[1] | int/long[3] | uint32 | Fixnum or Bignum | uint |
| uint64 | uint64 | long[1] | int/long[3] | uint64 | Bignum | ulong |
| sint32 | int32 | int | intj | int32 | Fixnum or Bignum | int |
| sint64 | int64 | long | int/long[3] | int64 | Bignum | long |
| fixed32 | uint32 | int[1] | int | uint32 | Fixnum or Bignum | uint |
| fixed64 | uint64 | long[1] | int/long[3] | uint64 | Bignum | ulong |
| sfixed32 | int32 | int | int | int32 | Fixnum or Bignum | int |
| sfixed64 | int64 | long | int/long[3] | int64 | Bignum | long |
| bool | bool | boolean | boolean | bool | TrueClass/FalseClass | bool |
| string | string | String | str/unicode[4] | string | String(UTF-8) | string |
| bytes | string | ByteString | str | []byte | String(ASCII-8BIT) | ByteString |
字段名稱
- 字段名稱的命名與C、C++、Java等語(yǔ)言的變量命名方式幾乎是相同的
- protobuf建議字段的命名采用以下劃線分割的駝峰式。例如 first_name 而不是firstName
字段編碼值
- 有了該值,通信雙方才能互相識(shí)別對(duì)方的字段,相同的編碼值,其限定修飾符和數(shù)據(jù)類(lèi)型必須相同,編碼值的取值范圍為
1~2^32(4294967296) - 其中 1~15的編碼時(shí)間和空間效率都是最高的,編碼值越大,其編碼的時(shí)間和空間效率就越低,所以建議把經(jīng)常要傳遞的值把其字段編碼設(shè)置為1-15之間的值
- 1900~2000編碼值為Google protobuf 系統(tǒng)內(nèi)部保留值,建議不要在自己的項(xiàng)目中使用
字段默認(rèn)值
當(dāng)在傳遞數(shù)據(jù)時(shí),對(duì)于required數(shù)據(jù)類(lèi)型,如果用戶沒(méi)有設(shè)置值,則使用默認(rèn)值傳遞到對(duì)端
1.3 service如何定義
- 如果想要將消息類(lèi)型用在RPC系統(tǒng)中,可以在.proto文件中定義一個(gè)RPC服務(wù)接口,protocol buffer編譯器會(huì)根據(jù)所選擇的不同語(yǔ)言生成服務(wù)接口代碼
- 例如,想要定義一個(gè)RPC服務(wù)并具有一個(gè)方法,該方法接收SearchRequest并返回一個(gè)SearchResponse,此時(shí)可以在.proto文件中進(jìn)行如下定義:
service SearchService {
rpc Search (SearchRequest) returns (SearchResponse) {}
}
- 生成的接口代碼作為客戶端與服務(wù)端的約定,服務(wù)端必須實(shí)現(xiàn)定義的所有接口方法,客戶端直接調(diào)用同名方法向服務(wù)端發(fā)起請(qǐng)求,比較麻煩的是,即便業(yè)務(wù)上不需要參數(shù)也必須指定一個(gè)請(qǐng)求消息,一般會(huì)定義一個(gè)空message
1.4 Message如何定義
- 一個(gè)message類(lèi)型定義描述了一個(gè)請(qǐng)求或響應(yīng)的消息格式,可以包含多種類(lèi)型字段
- 例如定義一個(gè)搜索請(qǐng)求的消息格式,每個(gè)請(qǐng)求包含查詢字符串、頁(yè)碼、每頁(yè)數(shù)目
- 字段名用小寫(xiě),轉(zhuǎn)為go文件后自動(dòng)變?yōu)榇髮?xiě),message就相當(dāng)于結(jié)構(gòu)體
syntax = "proto3";
message SearchRequest {
string query = 1; // 查詢字符串
int32 page_number = 2; // 頁(yè)碼
int32 result_per_page = 3; // 每頁(yè)條數(shù)
}
- 首行聲明使用的protobuf版本為proto3
- SearchRequest 定義了三個(gè)字段,每個(gè)字段聲明以分號(hào)結(jié)尾,.proto文件支持雙斜線 // 添加單行注釋
四 proto代碼編寫(xiě)
- 在account.proto文件中寫(xiě)入以下代碼
syntax = "proto3";
import "google/protobuf/timestamp.proto";
package go.micro.service.account;
option go_package="/proto/account";
service Account {
//登錄
rpc Login(LoginRequest) returns (LoginResponse) {}
//注冊(cè)
rpc Register(RegisterRequest) returns (RegisterResponse) {}
//查詢用戶信息
rpc GetUserInfo(UserIdRequest) returns (UserInfoResponse) {}
//修改信息
rpc UpdateUserInfo(UserInfoRequest) returns (Response) {}
//發(fā)送注冊(cè)郵件
rpc SendRegisterMail(SendMailRequest) returns (SendMailResponse) {}
//發(fā)送重置密碼郵件
rpc SendResetPwdMail(SendMailRequest) returns (SendMailResponse) {}
//重置密碼
rpc ResetPwd(ResetPwdRequest) returns (Response) {}
//獲取權(quán)限
rpc GetUserPermission(UserIdRequest) returns (GetPermissionResponse) {}
//修改權(quán)限
rpc UpdateUserPermission(UpdatePermissionRequest) returns (Response) {}
//退出賬號(hào)
rpc Logout(UserIdRequest) returns (Response) {}
//刪除賬號(hào)
rpc DelUser(UserIdRequest) returns (Response) {}
//禁用賬號(hào)
rpc DisableUser(UserIdRequest) returns (Response) {}
//啟用賬號(hào)
rpc EnableUser(UserIdRequest) returns (Response) {}
}
message UserInfoResponse{
int64 user_id = 1;
string username = 2;
string first_name = 3;
string password = 4;
int64 permission = 5;
google.protobuf.Timestamp create_date = 6;
google.protobuf.Timestamp update_date = 7;
int64 is_active = 8;
string email = 9;
string last_name = 10;
}
message UserInfoRequest{
UserInfoResponse user_info =1;
}
message UserIdRequest{
int64 user_id = 1;
}
message Response{
string message = 1;
}
message RegisterRequest{
UserInfoResponse register_request = 1;
string code = 2;
}
message LoginRequest{
string username = 1;
string password = 2;
}
message LoginResponse{
bool is_success = 1;
int64 user_id = 2;
string token = 3;
}
message RegisterResponse{
bool is_success = 1;
int64 user_id = 2;
}
message SendMailRequest{
string email = 1;
}
message SendMailResponse{
string code = 1;
string msg = 2;
}
message GetPermissionResponse{
int64 permission = 1;
}
message UpdatePermissionRequest{
int64 user_id = 1;
int64 permission = 2;
}
message ResetPwdRequest{
int64 user_id = 1;
string code = 2;
string password = 3;
}
五 生成.go文件
-打開(kāi)終端,輸入以下命令:
protoc --go_out=./ --micro_out=./ ./proto/account/account.proto
- 命令執(zhí)行后,會(huì)發(fā)現(xiàn)同級(jí)目錄多了兩個(gè)go文件,這就是自動(dòng)生成好的編譯之后的文件。
- 命令講解:
- --go_out 指定當(dāng)前的目錄./
- --micro_out 指定當(dāng)前micro目錄./
- ./proto/account/account.proto 指定要編譯的.proto文件地址
效果圖:

六 最后
- 至此,go-micro微服務(wù)項(xiàng)目proto開(kāi)發(fā)工作就正式完成。
- 接下來(lái)就開(kāi)始domain層開(kāi)發(fā)了,希望大家關(guān)注博主和關(guān)注專(zhuān)欄,第一時(shí)間獲取最新內(nèi)容,每篇博客都干貨滿滿。
以上就是go micro微服務(wù)proto開(kāi)發(fā)安裝及使用規(guī)則的詳細(xì)內(nèi)容,更多關(guān)于go micro微服務(wù)proto的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
go-micro使用Consul做服務(wù)發(fā)現(xiàn)的方法和原理解析
這篇文章主要介紹了go-micro使用Consul做服務(wù)發(fā)現(xiàn)的方法和原理,這里提供一個(gè)通過(guò)docker快速安裝Consul的方式,當(dāng)然前提是你得安裝了docker,需要的朋友可以參考下2022-04-04
Golang 如何判斷數(shù)組某個(gè)元素是否存在 (isset)
這篇文章主要介紹了Golang 如何判斷數(shù)組某個(gè)元素是否存在 (isset),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-04-04
Go語(yǔ)言驅(qū)動(dòng)低代碼應(yīng)用引擎工具Yao開(kāi)發(fā)管理系統(tǒng)
這篇文章主要為大家介紹了Go語(yǔ)言驅(qū)動(dòng)低代碼應(yīng)用引擎工具Yao開(kāi)發(fā)管理系統(tǒng)使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06
Go語(yǔ)言使用sort包對(duì)任意類(lèi)型元素的集合進(jìn)行排序的方法
這篇文章主要介紹了Go語(yǔ)言使用sort包對(duì)任意類(lèi)型元素的集合進(jìn)行排序的方法,實(shí)例分析了sort排序所涉及的方法與相關(guān)的使用技巧,需要的朋友可以參考下2015-02-02
VSCode安裝go相關(guān)插件失敗的簡(jiǎn)單解決方案
這篇文章主要給大家介紹了關(guān)于VSCode安裝go相關(guān)插件失敗的簡(jiǎn)單解決方案,VSCode是我們開(kāi)發(fā)go程序的常用工具,最近安裝的時(shí)候遇到了些問(wèn)題,需要的朋友可以參考下2023-07-07
Golang 利用反射對(duì)結(jié)構(gòu)體優(yōu)雅排序的操作方法
這篇文章主要介紹了Golang 利用反射對(duì)結(jié)構(gòu)體優(yōu)雅排序的操作方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-10-10
Go?slice切片make生成append追加copy復(fù)制示例
這篇文章主要為大家介紹了Go使用make生成切片、使用append追加切片元素、使用copy復(fù)制切片使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06
go貨幣計(jì)算時(shí)如何避免浮點(diǎn)數(shù)精度問(wèn)題
在開(kāi)發(fā)的初始階段,我們經(jīng)常會(huì)遇到“浮點(diǎn)數(shù)精度”和“貨幣值表示”的問(wèn)題,那么在golang中如何避免這一方面的問(wèn)題呢,下面就跟隨小編一起來(lái)學(xué)習(xí)一下吧2024-02-02

