// example
// file kittens/video_ext.proto
import "kittens/video.proto";
import "media/user_content.proto";
package kittens;
// This extension allows kitten videos in a media.UserContent message.
extend media.UserContent {
// Video is a message imported from kittens/video.proto
repeated Video kitten_videos = 126;
}
// file media/user_content.proto
package media;
// A container message to hold stuff that a user has created.
message UserContent {
extensions 100 to 199;
}
Protocol Buffers允许定义和使用自己的选项。但是这是大多数人不需要的高级功能。
由于选项是由 google/protobuf/descriptor.proto 中定义的Message(如 FileOptions 或 FieldOptions),
定义自己的选项都只是扩展这些Message。例如:
import "google/protobuf/descriptor.proto";
extend google.protobuf.FileOptions {
optional string my_file_option = 50000;
}
extend google.protobuf.MessageOptions {
optional int32 my_message_option = 50001;
}
extend google.protobuf.FieldOptions {
optional float my_field_option = 50002;
}
extend google.protobuf.OneofOptions {
optional int64 my_oneof_option = 50003;
}
extend google.protobuf.EnumOptions {
optional bool my_enum_option = 50004;
}
extend google.protobuf.EnumValueOptions {
optional uint32 my_enum_value_option = 50005;
}
extend google.protobuf.ServiceOptions {
optional MyEnum my_service_option = 50006;
}
extend google.protobuf.MethodOptions {
optional MyMessage my_method_option = 50007;
}
option (my_file_option) = "Hello world!";
message MyMessage {
option (my_message_option) = 1234;
optional int32 foo = 1 [(my_field_option) = 4.5];
optional string bar = 2;
oneof qux {
option (my_oneof_option) = 42;
string quux = 3;
}
}
enum MyEnum {
option (my_enum_option) = true;
FOO = 1 [(my_enum_value_option) = 321];
BAR = 2;
}
message RequestType {}
message ResponseType {}
service MyService {
option (my_service_option) = FOO;
rpc MyMethod(RequestType) returns(ResponseType) {
// Note: my_method_option has type MyMessage. We can set each field
// within it using a separate "option" line.
option (my_method_option).foo = 567;
option (my_method_option).bar = "Some string";
}
rpc OtherMethod(RequestType) returns(ResponseType) {
option (my_method_option) = {
foo: 567,
bar: "Some string"
};
}
}
// ---------------------------------------------------------
// 请注意,如果您想在定义它的包之外的包中使用自定义选项,则必须在选项名称前加上包名称前缀,就像您在类型名称中所做的那样。例如
// foo.proto
import "google/protobuf/descriptor.proto";
package foo;
extend google.protobuf.MessageOptions {
optional string my_option = 51234;
}
// bar.proto
import "foo.proto";
package bar;
message OtherMessage {
option (foo.my_option) = "Hello world!";
}
- 自定义http Option
3.1 利用google预定义的Option https://github.com/googleapis/googleapis
下载以下两个文件到一个目录下,在执行protoc时候通过-I指定目录,能够使其他proto文件import
google/api/annotations.proto
google/api/http.proto
两个文件proto通过protoc的go代码 在 google.golang.org/genproto/googleapis/api/annotations
3.2 完全自定义Option [参考custom/http.proto]
// 运行以下 生成http.pb.go 这个文件需要能够后期被引用到
// 如果没安装protoc-gen-go插件 用go install安装
// go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
protoc --go_out . --go_opt=paths=source_relative ./custom/http.proto
# install
go install https://github.com/DouFuJuShi/protoc-gen-go-gin@latest
# about other proto files
# how to use
protoc \
-I ./examples/api \
--go_out ./examples/api --go_opt=paths=source_relative \
--go-gin_out ./examples/api --go-gin_opt=paths=source_relative \
./examples/api/hello/v1/hello.proto
# install
go install https://github.com/favadi/protoc-go-inject-tag@latest
# inject tags
protoc-go-inject-tag -input=hello.pb.go
// user.proto
message HelloRequest {
// @gotags: form:"title" uri:"id"
string UserId = 1;
}
// user.pb.go
// see UserId's struct tags
type HelloRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// @gotags: form:"title" uri:"id"
UserId string `protobuf:"bytes,1,opt,name=UserId,proto3" json:"UserId,omitempty" form:"title" uri:"id"`
}
TKS!!!