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生成失败报错
虽然还有些地方没弄清楚,但好歹都解决了,记录一下供学习。