GolangとProtobuf
文書ディレクトリ 1. Protobuf紹介 2. Protobufの特徴 3. Protobuf環境構成 3.1 protobuf基礎ツール をインストールする 3.2プログラミング言語プラグイン をインストール 3.3 Protobufベース使用 4. Protobufプロトコル構文 5. ProtobufとRPC 1.Protobufの紹介
ProtobufはProtocol Buffersの略称であり、Googleオープンソースのデータ記述言語であり、XMLやjsonなどのデータ記述言語に類似した初期位置にある.Protobufの最も一般的な使用シーンはRPCシステムに用いられる.これはprotobufが軽量で効率的な構造化データ記憶フォーマットであり、シーケンス化が可能であり、データ記憶やRPCデータインタラクティブフォーマットに適しているからである.
2.Protobufの特徴
**メリット:** protobufは効率的なバイナリストレージで、占有空間はXMLより3~10倍小さく、解析速度は20~100倍速い コード生成メカニズム マルチプログラミング言語サポート 互換性が良い 欠点:は可読性が悪く、デバッグが相対的に困難である protobufの詳細については、以下を参照してください.
https://developers.google.com/protocol-buffers
3.Protobuf環境構成
3.1 protobufインフラストラクチャのインストール自己開発システムに基づいてprotobufコンパイラをダウンロード
ダウンロードアドレスhttps://github.com/protocolbuffers/protobuf/releases
環境変数 の構成 が正常にインストールされていることを確認します.
3.2プログラミング言語プラグインのインストール
Go言語のコード生成プラグインを選択しました
コマンドラインで実行
このコマンドの実行が完了すると、このようなディレクトリが表示されます.
インストールに成功すると、$GOPATH/binディレクトリの下で
Go言語のコード生成プラグインをインストールした後、次の手順でテストします.
|
|__example
|____ demo2.proto
ファイルはexample/demo 2です.proto
tips:次のコマンドが有効でない場合は、
上記のコマンドについて簡単に説明します.
実際の使用中にパラメータを柔軟に使用すればよい
|
|__example
|____ demo2.proto
|____ demo2.pb.go
この新しいファイルは自動生成go言語コードです. 開発の過程で の違いがある.で生成されたコードは、通常、 に注目する必要はありません.ビジネス層では、必要に応じて自動生成コードファイルで提供する のみを使用する.
3.3 Protobufベースの使用
|
|__example
|____ demo2.proto
|____ demo2.pb.go
|__ main.go
**Protobuf基本使用公式ドキュメントを参照することを強くお勧めします:**
⭐️ https://developers.google.com/protocol-buffers/docs/gotutorial
4.Protobufプロトコル構文
作成された Protobufの構文は比較的簡単です Protobufの語現在 proto2 https://developers.google.com/protocol-buffers/docs/proto proto3 https://developers.google.com/protocol-buffers/docs/proto3
プロジェクトに履歴的な負担がない場合は、proto 3の構文を使用して を作成することを強くお勧めします.
5.ProtobufとRPC
ProtobufとRPCを組み合わせて簡単なDemoを作ります
手順は次のとおりです.作成 自動生成コード RPCを記述するサービス端末 PRCを記述するクライアント 実行テスト ディレクトリ構造は次のとおりです.
rpcサービス側ファイル
rpcクライアントファイル
運転
ProtobufはProtocol Buffersの略称であり、Googleオープンソースのデータ記述言語であり、XMLやjsonなどのデータ記述言語に類似した初期位置にある.Protobufの最も一般的な使用シーンはRPCシステムに用いられる.これはprotobufが軽量で効率的な構造化データ記憶フォーマットであり、シーケンス化が可能であり、データ記憶やRPCデータインタラクティブフォーマットに適しているからである.
2.Protobufの特徴
**メリット:**
https://developers.google.com/protocol-buffers
3.Protobuf環境構成
3.1 protobufインフラストラクチャのインストール
ダウンロードアドレスhttps://github.com/protocolbuffers/protobuf/releases
# protobuf
$ protoc --version
libprotoc 3.11.0
#
$ protoc --help
.
.
.
--cpp_out=OUT_DIR Generate C++ header and source.
--csharp_out=OUT_DIR Generate C# source file.
--java_out=OUT_DIR Generate Java source file.
--js_out=OUT_DIR Generate JavaScript source.
--objc_out=OUT_DIR Generate Objective C header and source.
--php_out=OUT_DIR Generate PHP source file.
--python_out=OUT_DIR Generate Python source file.
--ruby_out=OUT_DIR Generate Ruby source file.
@<filename> Read options and filenames from file. If a
relative file path is specified, the file
will be searched in the working directory.
The --proto_path option will not affect how
this argument file is searched. Content of
the file will be expanded in the position of
@<filename> as in the argument list. Note
that shell expansion is not applied to the
content of the file (i.e., you cannot use
quotes, wildcards, escapes, commands, etc.).
Each line corresponds to a single argument,
even if it contains spaces.
3.2プログラミング言語プラグインのインストール
Go言語のコード生成プラグインを選択しました
コマンドラインで実行
go get github.com/golang/protobuf/protoc-gen-go
このコマンドの実行が完了すると、このようなディレクトリが表示されます.
$GOPATH/src/github.com/golang/protobuf
インストールに成功すると、$GOPATH/binディレクトリの下で
protoc-gen-go
の実行可能ファイルが生成されます.Go言語のコード生成プラグインをインストールした後、次の手順でテストします.
.proto
を接尾辞とするprotobufファイルを記述する|
|__example
|____ demo2.proto
ファイルはexample/demo 2です.proto
syntax = "proto3"; // protobuf3
package example;
message Person {
string name = 1;
int32 age = 2;
enum Gender {
MALE = 0;
FEMALE = 1;
UNKNOWN = 2;
}
message Other {
string addr = 1;
string hobby = 2;
Gender g = 3;
}
Other info = 3;
}
protoc-gen-go
を使用してgo言語コードを生成tips:次のコマンドが有効でない場合は、
protoc-gen-go
の実行可能ファイルを$GOROOT/bin/
ディレクトリにコピーしてみてください. protoc --go_out=. example/demo2.proto
上記のコマンドについて簡単に説明します.
--go_out
パラメータは、protoc
コンパイラに対応するprotoc-gen-go
ツールをロードするように伝え、このツールによって対応するGolangコードを生成する=.
は、生成コードが現在のディレクトリに格納されていることを示します.もちろん、他のファイルディレクトリにも指定できます.example/demo2.protoc
はprotobufファイルのパスです実際の使用中にパラメータを柔軟に使用すればよい
demo2.pb.go
というファイルが生成されます|
|__example
|____ demo2.proto
|____ demo2.pb.go
この新しいファイルは自動生成go言語コードです.
demo2.pb.go
のコードの一部を見てみましょう..proto
ファイルを定義した後、このコードはプラグインが自動的に生成し、異なるプログラミング言語の文法には
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: demo2.proto
package example
import (
fmt "fmt"
proto "github.com/golang/protobuf/proto"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
type Person_Gender int32
const (
Person_MALE Person_Gender = 0
Person_FEMALE Person_Gender = 1
Person_UNKNOWN Person_Gender = 2
)
var Person_Gender_name = map[int32]string{
0: "MALE",
1: "FEMALE",
2: "UNKNOWN",
}
var Person_Gender_value = map[string]int32{
"MALE": 0,
"FEMALE": 1,
"UNKNOWN": 2,
}
func (x Person_Gender) String() string {
return proto.EnumName(Person_Gender_name, int32(x))
}
func (Person_Gender) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_80e54830e2bc2dba, []int{0, 0}
}
type Person struct {
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Age int32 `protobuf:"varint,2,opt,name=age,proto3" json:"age,omitempty"`
Info *Person_Other `protobuf:"bytes,3,opt,name=info,proto3" json:"info,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Person) Reset() { *m = Person{} }
func (m *Person) String() string { return proto.CompactTextString(m) }
func (*Person) ProtoMessage() {}
func (*Person) Descriptor() ([]byte, []int) {
return fileDescriptor_80e54830e2bc2dba, []int{0}
}
func (m *Person) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Person.Unmarshal(m, b)
}
func (m *Person) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Person.Marshal(b, m, deterministic)
}
func (m *Person) XXX_Merge(src proto.Message) {
xxx_messageInfo_Person.Merge(m, src)
}
func (m *Person) XXX_Size() int {
return xxx_messageInfo_Person.Size(m)
}
func (m *Person) XXX_DiscardUnknown() {
xxx_messageInfo_Person.DiscardUnknown(m)
}
var xxx_messageInfo_Person proto.InternalMessageInfo
func (m *Person) GetName() string {
if m != nil {
return m.Name
}
return ""
}
func (m *Person) GetAge() int32 {
if m != nil {
return m.Age
}
return 0
}
func (m *Person) GetInfo() *Person_Other {
if m != nil {
return m.Info
}
return nil
}
type Person_Other struct {
Addr string `protobuf:"bytes,1,opt,name=addr,proto3" json:"addr,omitempty"`
Hobby string `protobuf:"bytes,2,opt,name=hobby,proto3" json:"hobby,omitempty"`
G Person_Gender `protobuf:"varint,3,opt,name=g,proto3,enum=example.Person_Gender" json:"g,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
3.3 Protobufベースの使用
|
|__example
|____ demo2.proto
|____ demo2.pb.go
|__ main.go
main.go
package main
import (
"GoNote/chapter10/demo9/example"
"fmt"
"github.com/golang/protobuf/proto"
"log"
)
func main() {
// Person
// Person
d1 := example.Person{
Name: "tom",
Age: 99,
Info: &example.Person_Other{
Addr: "beijing",
Hobby: "code",
G: example.Person_MALE,
},
}
//
d1Encode, err := proto.Marshal(&d1)
if err != nil {
log.Fatal(err.Error())
}
fmt.Println(d1Encode)
//
d1Decode := example.Person{}
err = proto.Unmarshal(d1Encode, &d1Decode)
if err != nil {
log.Fatal(err.Error())
}
fmt.Println(d1Decode.GetName())
fmt.Println(d1Decode.GetAge())
fmt.Println(d1Decode.GetInfo().GetG())
}
go run main.go
[10 3 116 111 109 16 99 26 15 10 7 98 101 105 106 105 110 103 18 4 99 111 100 101]
tom
99
MALE
**Protobuf基本使用公式ドキュメントを参照することを強くお勧めします:**
⭐️ https://developers.google.com/protocol-buffers/docs/gotutorial
4.Protobufプロトコル構文
作成された
.proto
ファイルは、特定の構文フォーマットで作成されていることに気づきました.proto2
とproto3
の2つのバージョン.proto
ファイル5.ProtobufとRPC
ProtobufとRPCを組み合わせて簡単なDemoを作ります
手順は次のとおりです.
.proto
ファイル.pb.go
のコードファイル|
|___example
|______demo3.proto
|______demo3.pb.go
|___main
|______demo3_server.go
|______demo3_client.go
demo3.proto
ファイルの作成syntax = "proto3"; // protobuf3
package example;
message Demo3Request {
int64 id = 1;
}
message Demo3Response {
string name = 1;
int32 age = 2;
enum Gender {
MALE = 0;
FEMALE = 1;
UNKNOWN = 2;
}
message Other {
string addr = 1;
string hobby = 2;
Gender g = 3;
}
Other info = 3;
}
.pb.go
ファイルの生成protoc --go_out=. demo3.proto
rpcサービス側ファイル
demo3_server.go
の作成package main
import (
"GoNote/chapter10/demo9/example"
"github.com/pkg/errors"
"log"
"net/http"
"net/rpc"
)
type Demo3Service struct {
}
func (d *Demo3Service) GetUser(request example.Demo3Request, response *example.Demo3Response) error {
//
//
datas := map[int64]example.Demo3Response{
1: {Name: "AAA", Age: 999, Info: &example.Demo3Response_Other{Addr: "beijing", Hobby: "sport", G: example.Demo3Response_MALE}},
2: {Name: "BBB", Age: 888, Info: &example.Demo3Response_Other{Addr: " ", Hobby: "sport", G: example.Demo3Response_FEMALE}},
3: {Name: "CCC", Age: 777, Info: &example.Demo3Response_Other{Addr: "wuhan", Hobby: "sport", G: example.Demo3Response_UNKNOWN}},
4: {Name: "DDD", Age: 666, Info: &example.Demo3Response_Other{Addr: " ", Hobby: "sport", G: example.Demo3Response_MALE}},
5: {Name: "EEE", Age: 555, Info: &example.Demo3Response_Other{Addr: "", Hobby: "sport", G: example.Demo3Response_FEMALE}},
}
//
if value, ok := datas[request.GetId()]; ok {
*response = value
} else {
return errors.New("not found")
}
return nil
}
func main() {
rpc.Register(new(Demo3Service))
rpc.HandleHTTP()
err := http.ListenAndServe(":8080", nil)
if err != nil {
log.Println(err.Error())
}
}
rpcクライアントファイル
demo3_client.go
の作成package main
import (
"GoNote/chapter10/demo9/example"
"fmt"
"log"
"net/rpc"
)
func main() {
client, err := rpc.DialHTTP("tcp", ":8080")
if err != nil {
log.Fatal(err.Error())
}
request := example.Demo3Request{Id: 1}
var response example.Demo3Response
err = client.Call("Demo3Service.GetUser", request, &response)
if err != nil {
log.Fatal(err.Error())
}
fmt.Println(response.GetName())
fmt.Println(response.GetInfo().GetAddr())
}
運転
demo3_server.go
およびdemo3_client.go
AAA
beijing