百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分析 > 正文

Protobuf生成Go代码指南 protobuf编写

liebian365 2024-10-24 14:38 12 浏览 0 评论

这个教程中将会描述protocol buffer编译器通过给定的.proto会编译生成什么Go代码。教程针对的是proto3版本的protobuf。在阅读之前确保你已经阅读过Protobuf语言指南。

编译器调用

Protobuf核心的工具集是C++语言开发的,官方的protoc编译器中并不支持Go语言,需要安装一个插件才能生成Go代码。用如下命令安装:

$ go get github.com/golang/protobuf/protoc-gen-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标志指定)。

当你运行如下编译命令时:

protoc --proto_path=src --go_out=build/gen src/foo.proto src/bar/baz.proto

编译器会读取文件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。

消息

一个简单的消息声明:

message Foo {}

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。

单一标量字段

对于字段定义:

int32 foo = 1;

编译器将生成一个带有名为Foo的int32字段和一个访问器方法GetFoo()的结构,该方法返回Foo中的int32值或该字段的零值(如果字段未设置(数值型零值为0,字符串为空字符串))。

单一message字段

给出如下消息类型

message Bar {}

对于一个有Bar类型字段的消息:

编译器将会生成一个Go结构体

消息类型的字段可以设置为nil,这意味着该字段未设置,有效清除该字段。这不等同于将值设置为消息结构体的“空”实例。

编译器还生成一个func(m * Baz)GetFoo()* Bar辅助函数。这让不在中间检查nil值进行链式调用成为可能。

可重复字段

每个重复的字段在Go中的结构中生成一个T类型的slice,其中T是字段的元素类型。对于带有重复字段的此消息:

编译器会生成如下结构体:

同样,对于字段定义repeated bytes foo = 1;编译器将会生成一个带有类型为[][]byte名为Foo的字段的Go结构体。对于可重复的枚举repeated MyEnum bar = 2;,编译器会生成带有类型为[]MyEnum名为Bar的字段的Go结构体。

映射字段

每个映射字段会在Go的结构体中生成一个map[TKey]TValue类型的字段,其中TKey是字段的键类型TValue是字段的值类型。对于下面这个消息定义:

编译器生成Go结构体

枚举

给出如下枚举

编译器将会生成一个枚举类型和一系列该类型的常量。

对于消息中的枚举(像上面那样),类型名字以消息名开头

type SearchRequest_Corpus int32

对于包级别的枚举:

Go 中的类型不会对proto中的枚举名称进行修改:

type Foo int32

此类型具有String()方法,该方法返回给定值的名称。

Enum()方法使用给定值初始化新分配的内存并返回相应的指针:

func (Foo) Enum() *Foo

编译器为枚举中的每个值生成一个常量。对于消息中的枚举,常量以消息的名称开头:

对于包级别的枚举,常量以枚举名称开头:

protobuf编译器还生成从整数值到字符串名称的映射以及从名称到值的映射:

请注意,.proto语言允许多个枚举符号具有相同的数值。具有相同数值的符号是同义词。这些在Go中以完全相同的方式表示,多个名称对应于相同的数值。反向映射包含数字值的单个条目,数值映射到出现在proto文件中首先出现的名称。

服务

默认情况下,Go代码生成器不会为服务生成输出。如果您启用gRPC插件(请参阅gRPC Go快速入门指南),则会生成代码以支持gRPC。

本文作者:KevinYan

原文链接:https://segmentfault.com/a/1190000020418571

相关推荐

快递查询教程,批量查询物流,一键管理快递

作为商家,每天需要查询许许多多的快递单号,面对不同的快递公司,有没有简单一点的物流查询方法呢?小编的回答当然是有的,下面随小编一起来试试这个新技巧。需要哪些工具?安装一个快递批量查询高手快递单号怎么快...

一键自动查询所有快递的物流信息 支持圆通、韵达等多家快递

对于各位商家来说拥有一个好的快递软件,能够有效的提高自己的工作效率,在管理快递单号的时候都需要对单号进行表格整理,那怎么样能够快速的查询所有单号信息,并自动生成表格呢?1、其实方法很简单,我们不需要一...

快递查询单号查询,怎么查物流到哪了

输入单号怎么查快递到哪里去了呢?今天小编给大家分享一个新的技巧,它支持多家快递,一次能查询多个单号物流,还可对查询到的物流进行分析、筛选以及导出,下面一起来试试。需要哪些工具?安装一个快递批量查询高手...

3分钟查询物流,教你一键批量查询全部物流信息

很多朋友在问,如何在短时间内把单号的物流信息查询出来,查询完成后筛选已签收件、筛选未签收件,今天小编就分享一款物流查询神器,感兴趣的朋友接着往下看。第一步,运行【快递批量查询高手】在主界面中点击【添...

快递单号查询,一次性查询全部物流信息

现在各种快递的查询方式,各有各的好,各有各的劣,总的来说,还是有比较方便的。今天小编就给大家分享一个新的技巧,支持多家快递,一次能查询多个单号的物流,还能对查询到的物流进行分析、筛选以及导出,下面一起...

快递查询工具,批量查询多个快递快递单号的物流状态、签收时间

最近有朋友在问,怎么快速查询单号的物流信息呢?除了官网,还有没有更简单的方法呢?小编的回答当然是有的,下面一起来看看。需要哪些工具?安装一个快递批量查询高手多个京东的快递单号怎么快速查询?进入快递批量...

快递查询软件,自动识别查询快递单号查询方法

当你拥有多个快递单号的时候,该如何快速查询物流信息?比如单号没有快递公司时,又该如何自动识别再去查询呢?不知道如何操作的宝贝们,下面随小编一起来试试。需要哪些工具?安装一个快递批量查询高手快递单号若干...

教你怎样查询快递查询单号并保存物流信息

商家发货,快递揽收后,一般会直接手动复制到官网上一个个查询物流,那么久而久之,就会觉得查询变得特别繁琐,今天小编给大家分享一个新的技巧,下面一起来试试。教程之前,我们来预览一下用快递批量查询高手...

简单几步骤查询所有快递物流信息

在高峰期订单量大的时候,可能需要一双手当十双手去查询快递物流,但是由于逐一去查询,效率极低,追踪困难。那么今天小编给大家分享一个新的技巧,一次能查询多个快递单号的物流,下面一起来学习一下,希望能给大家...

物流单号查询,如何查询快递信息,按最后更新时间搜索需要的单号

最近有很多朋友在问,如何通过快递单号查询物流信息,并按最后更新时间搜索出需要的单号呢?下面随小编一起来试试吧。需要哪些工具?安装一个快递批量查询高手快递单号若干怎么快速查询?运行【快递批量查询高手】...

连续保存新单号功能解析,导入单号查询并自动识别批量查快递信息

快递查询已经成为我们日常生活中不可或缺的一部分。然而,面对海量的快递单号,如何高效、准确地查询每一个快递的物流信息,成为了许多人头疼的问题。幸运的是,随着科技的进步,一款名为“快递批量查询高手”的软件...

快递查询教程,快递单号查询,筛选更新量为1的单号

最近有很多朋友在问,怎么快速查询快递单号的物流,并筛选出更新量为1的单号呢?今天小编给大家分享一个新方法,一起来试试吧。需要哪些工具?安装一个快递批量查询高手多个快递单号怎么快速查询?运行【快递批量查...

掌握批量查询快递动态的技巧,一键查找无信息记录的两种方法解析

在快节奏的商业环境中,高效的物流查询是确保业务顺畅运行的关键。作为快递查询达人,我深知时间的宝贵,因此,今天我将向大家介绍一款强大的工具——快递批量查询高手软件。这款软件能够帮助你批量查询快递动态,一...

从复杂到简单的单号查询,一键清除单号中的符号并批量查快递信息

在繁忙的商务与日常生活中,快递查询已成为不可或缺的一环。然而,面对海量的单号,逐一查询不仅耗时费力,还容易出错。现在,有了快递批量查询高手软件,一切变得简单明了。只需一键,即可搞定单号查询,一键处理单...

物流单号查询,在哪里查询快递

如果在快递单号多的情况,你还在一个个复制粘贴到官网上手动查询,是一件非常麻烦的事情。于是乎今天小编给大家分享一个新的技巧,下面一起来试试。需要哪些工具?安装一个快递批量查询高手快递单号怎么快速查询?...

取消回复欢迎 发表评论: