内容简介:这个教程中将会描述protocol buffer编译器通过给定的Protobuf核心的工具集是C++语言开发的,官方的protoc编译器中并不支持Go语言,需要安装一个插件才能生成Go代码。用如下命令安装:提供了一个
这个教程中将会描述protocol buffer编译器通过给定的 .proto
会编译生成什么 Go 代码。教程针对的是proto3版本的protobuf。在阅读之前确保你已经阅读过Protobuf语言指南。
编译器调用
Protobuf核心的 工具 集是C++语言开发的,官方的protoc编译器中并不支持Go语言,需要安装一个插件才能生成Go代码。用如下命令安装:
提供了一个 protoc-gen-go
二进制文件,当编译器调用时传递了 --go_out
命令行标志时 protoc
就会使用它。 --go_out
告诉编译器把Go源代码写到哪里。编译器会为每个 .proto
文件生成一个单独的源代码文件。
输出文件的名称是通过获取.proto文件的名称并进行两处更改来计算的:
-
生成文件的扩展名是
.pb.go
。比如说player_record.proto
编译后会得到player_record.pb.go
。 -
proto路径(使用
--proto_path
或-I
命令行标志指定)将替换为输出路径(使用--go_out
标志指定)。
当你运行如下编译命令时:
编译器会读取文件 src/foo.proto
和 src/bar/baz.proto
,这将会生成两个输出文件 build/gen/foo.pb.go
和 build/gen/bar/baz.pb.go
如果有必要,编译器会自动生成 build/gen/bar
目录,但是他不能创建 build
或者 build/gen
目录,这两个必须是已经存在的目录。
包
如果一个 .proto
文件中有包声明,生成的源代码将会使用它来作为Go的包名,如果 .proto
的包名中有 .
在Go包名中会将 .
转换为 _
。举例来说 proto
包名 example.high_score
将会生成Go包名 example_high_score
。
在 .proto
文件中可以使用option go_package
指令来覆盖上面默认生成Go包名的规则。比如说包含如下指令的一个 .proto
文件
生成的Go源代码的包名是 hs
。
如果一个 .proto
文件中不包含package声明,生成的源代码将会使用 .proto
文件的文件名(去掉扩展名)作为Go包名, .
会被首先转换为 _
。举例来说一个名为 high.score.proto
不包含pack声明的文件将会生成文件 high.score.pb.go
,他的Go包名是 high_score
。
消息
一个简单的消息声明:
protocol buffer编译器将会生成一个名为 Foo
的结构体,实现了 proto.Message
接口的 Foo
类型的指针
内嵌的消息
一个message可以声明在其他message的内部。比如说:
这种情况,编译器会生成两个结构体: Foo
和 Foo_Bar
。
预定义消息类型
Protobufs带有一组预定义的消息,称为众所周知的类型(WKT)。这些类型可以用于与其他服务的互操作性,或者仅仅因为它们简洁地表示了常见的有用模式。例如,Struct消息表示任意C样式结构的格式。
WKT的预生成Go代码作为Go protobuf库的一部分进行分发,如果message中使用了WKT,则生成的消息的Go代码会引用此代码。例如,给出如下消息:
生成的Go代码将会像下面这样:
一般来说,您不需要将这些类型直接导入代码中。但是,如果需要直接引用其中一种类型,只需导入github.com/golang/protobuf/ptypes/[TYPE]包,并正常使用该类型。
字段
编译器会为每个在message中定义的字段生成一个Go结构体的字段,字段的确切性质取决于它的类型以及它是 singular
, repeated
, map
还是 oneof
字段。
注意生成的Go结构体的字段将始终使用驼峰命名,即使在 .proto
文件中消息字段用的是小写加下划线(应该这样)。大小写转换的原理如下:
-
首字母会大些,如果message中字段的第一个字符是
_
,它将被替换为X。 -
如果内部下划线后跟小写字母,则删除下划线,并将后面跟随的字母大写。
因此,proto字段 foo_bar_baz
在Go中变成 FooBarBaz
, _my_field_name_2
变为 XMyFieldName_2
。
单一标量字段
对于字段定义:
编译器将生成一个带有名为Foo的int32字段和一个访问器方法GetFoo()的结构,该方法返回Foo中的int32值或该字段的零值(如果字段未设置(数值型零值为0,字符串为空字符串))。
单一message字段
给出如下消息类型
对于一个有 Bar
类型字段的消息:
编译器将会生成一个Go结构体
消息类型的字段可以设置为nil,这意味着该字段未设置,有效清除该字段。这不等同于将值设置为消息结构体的“空”实例。
编译器还生成一个 func(m*Baz)GetFoo()*Bar
辅助函数。这让不在中间检查nil值进行链式调用成为可能。
可重复字段
每个重复的字段在Go中的结构中生成一个T类型的slice,其中T是字段的元素类型。对于带有重复字段的此消息:
编译器会生成如下结构体:
同样,对于字段定义 repeated bytes foo=1;
编译器将会生成一个带有类型为 [][]byte
名为 Foo
的字段的Go结构体。对于可重复的枚举 repeatedMyEnumbar=2;
,编译器会生成带有类型为 []MyEnum
名为 Bar
的字段的Go结构体。
映射字段
每个映射字段会在Go的结构体中生成一个 map[TKey]TValue
类型的字段,其中 TKey
是字段的键类型 TValue
是字段的值类型。对于下面这个消息定义:
编译器生成Go结构体
枚举
给出如下枚举
编译器将会生成一个枚举类型和一系列该类型的常量。
对于消息中的枚举(像上面那样),类型名字以消息名开头
对于包级别的枚举:
Go 中的类型不会对proto中的枚举名称进行修改:
此类型具有 String()
方法,该方法返回给定值的名称。
Enum()
方法使用给定值初始化新分配的内存并返回相应的指针:
编译器为枚举中的每个值生成一个常量。对于消息中的枚举,常量以消息的名称开头:
对于包级别的枚举,常量以枚举名称开头:
protobuf编译器还生成从整数值到字符串名称的映射以及从名称到值的映射:
请注意, .proto
语言允许多个枚举符号具有相同的数值。具有相同数值的符号是同义词。这些在Go中以完全相同的方式表示,多个名称对应于相同的数值。反向映射包含数字值的单个条目,数值映射到出现在 proto
文件中首先出现的名称。
服务
默认情况下,Go代码生成器不会为服务生成输出。如果您启用gRPC插件(请参阅gRPC Go快速入门指南),则会生成代码以支持gRPC。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 利用代码生成工具生成基于ABP框架的代码
- 实战:一键生成前后端代码,Mybatis-Plus代码生成器让我舒服了
- 代码生成模式:未来我们会怎样写代码?
- JWCloud 专业版 v1.1.0 发布,新增代码生成器、一键生成模块及前端 UI 代码
- Java 代码生成
- Java代码生成器
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。