proto編譯組件使用
前提:所有組件已經安裝好,包括:
protoc
protoc-gen-go
protoc-gen-grpc-gateway
protoc-gen-swagger
怎么裝再開一篇
分為三個部分:
-
編譯pb.go
-
編譯pb.gw.go
-
編譯swagger.json
首先准備hello.proto文件:
syntax = "proto3";
package hello;
import "google/api/annotations.proto";
service HelloWorld {
rpc SayHelloWorld(HelloWorldRequest) returns (HelloWorldResponse) {
option (google.api.http) = {
post: "/hello_world"
body: "*"
};
}
}
message HelloWorldRequest {
string referer = 1;
}
message HelloWorldResponse {
string message = 1;
1. 編譯pb.go文件
需要使用protoc-gen-go組件,命令:
protoc --go_out=plugins=grpc:. ${xxx.proto}
注意要用-I參數引入相關的依賴,例如這里的google/api/annotations.proto:
protoc -I ./ -I $GOPATH/src -I $GOPATH/src/google/api --go_out=plugins=grpc:.
-
第一個
-I引入當前目錄(因為要用
hello.proto); -
第二個
-I引入go的相關依賴;
-
第三個
-I引入
annotations.proto這個文件,使用的前提是$GOPATN/src下已經准備好了相關的包;
完整命令:
protoc -I ./ -I $GOPATH/src -I $GOPATH/src/google/api --go_out=plugins=grpc:. ./hello.proto
輸出:
$ protoc -I ./ -I $GOPATH/src -I $GOPATH/src/google/api --go_out=plugins=grpc:. ./hello.proto
protoc-gen-go: unable to determine Go import path for "hello.proto"
Please specify either:
• a "go_package" option in the .proto source file, or
• a "M" argument on the command line.
See https://developers.google.com/protocol-buffers/docs/reference/go-generated#package for more information.
--go_out: protoc-gen-go: Plugin failed with status code 1.
看輸出需要在hello.proto文件中指定go_package參數,這里設置為當前目錄,更新下hello.proto內容:
syntax = "proto3";
package hello;
option go_package="./";
import "google/api/annotations.proto";
service HelloWorld {
rpc SayHelloWorld(HelloWorldRequest) returns (HelloWorldResponse) {
option (google.api.http) = {
post: "/hello_world"
body: "*"
};
}
}
message HelloWorldRequest {
string referer = 1;
}
message HelloWorldResponse {
string message = 1;
}
再次編譯,成功生成hello.pb.go文件。
2. 編譯pb.gw.go文件
需要使用protoc-gen-grpc-gateway 組件,命令:
protoc -I ./ -I $GOPATH/src -I $GOPATH/src/google/api --grpc-gateway_out=logtostderr=true:.
運行:
protoc -I ./ -I $GOPATH/src -I $GOPATH/src/google/api --grpc-gateway_out=logtostderr=true:. ./hello.proto
這時候命令行會輸出一大串東西,生成文件失敗,並且在最后標注了:
...
--grpc-gateway_out: 11:1: expected 'IDENT', found 'import'
試了很多方法,最后發現,go_package參數不能寫./,要加上后綴包名,例如改成./hello,不知道真正的原因是不是這個,但這樣改了以后編譯通過了。
這時候完整的hello.proto如下:
syntax = "proto3";
package hello;
option go_package="./hello";
import "google/api/annotations.proto";
service HelloWorld {
rpc SayHelloWorld(HelloWorldRequest) returns (HelloWorldResponse) {
option (google.api.http) = {
post: "/hello_world"
body: "*"
};
}
}
message HelloWorldRequest {
string referer = 1;
}
message HelloWorldResponse {
string message = 1;
}
重新運行上面的命令,成功生成 hello.pb.gw.go文件,此時目錄如下:
.
├── hello
│ └── hello.pb.gw.go
├── hello.pb.go
└── hello.proto
3. 編譯swagger.json文件
需要使用protoc-gen-swagger 組件,命令:
protoc -I ./ -I $GOPATH/src -I $GOPATH/src/google/api --swagger_out=logtostderr=true:.
運行:
protoc -I ./ -I $GOPATH/src -I $GOPATH/src/google/api --swagger_out=logtostderr=true:. ./hello.proto
變成成功,生成hello.swagger.json文件。
4. 總結
至此,三個文件都已經成功生成了,整理下目錄文件,如下:
.
├── hello.pb.go
├── hello.pb.gw.go
├── hello.proto
└── hello.swagger.json
其中踩了好幾個坑:
google/api/annotations.proto怎么解決- proto引入外部proto文件怎么處理
- gateway生成失敗報錯
雖然還有些地方沒弄清楚,但好歹都解決了,記錄一下供學習。
