Protobuf 生成Go 代码指南

发布时间:2025-05-12浏览:67

大家好,关于Protobuf 生成Go 代码指南很多朋友都还不太明白,不过没关系,因为今天小编就来为大家分享关于的知识点,相信应该可以解决大家的一些困惑和问题,如果碰巧可以解决您的问题,还望关注下本站哦,希望对各位有所帮助!

编译器调用

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_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_package 指令来覆盖上述默认生成Go 包名称的规则。例如,包含以下指令的.proto 文件

生成的Go源码的包名为hs。

信息

嵌入消息

在这种情况下,编译器将生成两个结构体:Foo和Foo_Bar。

预定义消息类型

Protobuf 附带一组预定义的消息,称为众所周知的类型(WKT)。这些类型可用于与其他服务的互操作性,或者仅仅因为它们简洁地表示常见的有用模式。例如,Struct 消息表示任意C 风格结构的格式。

WKT 的预生成Go 代码作为Go protobuf 库的一部分进行分发,如果在消息中使用WKT,则生成消息的Go 代码将引用此代码。例如,给出以下消息:

生成的Go 代码将如下所示:

一般来说,您不需要将这些类型直接导入到代码中。但是,如果您需要直接引用其中一种类型,只需导入github.com/golang/protobuf/ptypes/[TYPE] 包并正常使用该类型即可。

场地

编译器为消息中定义的每个字段生成一个Go 结构体字段。字段的确切性质取决于其类型以及它是单一字段、重复字段、映射字段还是oneof 字段。

请注意,生成的Go 结构体的字段将始终使用驼峰命名法命名,即使.proto 文件中的消息字段是小写并带有下划线(应该如此)。大小写转换的原理如下:

第一个字母会变大,如果message中字段的第一个字符是_,则会被X替换。如果内部下划线后面跟着小写字母,则删除下划线并将后面的字母大写。因此,原始字段foo_bar_baz 在Go 中变成了FooBarBaz,而_my_field_name_2 变成了XMyFieldName_2。

单标量场

对于字段定义:

int32 foo=1;编译器将生成一个结构体,其中包含一个名为Foo 的int32 字段和一个访问器方法GetFoo(),该方法返回Foo 中的int32 值,或者如果未设置该字段则返回该字段的零值(数字零值为0,字符串为空字符串))。

单个消息字段

给定以下消息类型

message Bar {} 用于具有Bar 类型字段的消息:

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

消息类型的字段可以设置为nil,表示该字段没有设置,从而有效地清除该字段。这并不等同于将该值设置为消息结构的“空”实例。

编译器还会生成func(m*Baz)GetFoo()*Bar 辅助函数。这使得链式调用无需检查中间的nil 值成为可能。

可重复字段

每个重复字段都会在Go 的结构体中生成一个T 类型的切片,其中T 是该字段的元素类型。对于此具有重复字段的消息:

编译器将生成以下结构:

类似地,对于字段定义重复字节foo=1;编译器将生成一个Go 结构体,其中包含一个名为Foo、类型为[][]byte 的字段。对于可重复枚举repeated MyEnum bar=2;编译器会生成一个Go结构体,其中包含一个名为Bar、类型为[]MyEnum的字段。

映射字段

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

编译器生成Go结构

枚举

给出以下枚举

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

对于消息中的枚举(如上),类型名称以消息名称开头

输入SearchRequest_Corpus int32 进行包级别枚举:

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

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

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

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

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

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

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

服务

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

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

用户评论

疲倦了

这个指南真的太棒了!以前对 Protobuf 了解不多,一直想尝试用它生成 Go 代码,结果照着教程一步步来,居然成功了!超赞的学习资源,感谢作者!

    有17位网友表示赞同!

凉城°

终于有个靠谱的 Protobuf 生成Go 代码指南!之前找了好久,很多都是老版本或者太难理解。这个指南讲得通俗易懂,而且示例很实用,让我快速上手Protobuf的使用。

    有18位网友表示赞同!

挽手余生ら

我觉得生成代码的部分还是比较简单,重点是理解 Protobuf 定义语言本身。如果能提供更多关于如何设计有效 Protobuf 消息的案例分析,那更好了!

    有19位网友表示赞同!

独角戏°

太棒了!这几天一直在为 protobuf 生成 Go 代码头疼,看到了这个指南感觉很欣喜,立刻试了一下,果然很给力!强烈推荐给所有想学习 Protobuf 的同学!

    有10位网友表示赞同!

半梦半醒i

我一直在使用 Protobuf 序列化数据,但是以前都是手动生成代码。现在有了这个指南,可以省去很多麻烦,真是太方便了!强烈建议把它收藏起来!

    有13位网友表示赞同!

瑾澜

看这篇文章时突然脑抽了一下,感觉Protobuf这种方式定义格式实在太笨拙了,直接用json或者yaml不就行了?还有比它更优雅的方案吧? 你们觉得呢?

    有15位网友表示赞同!

愁杀

虽然这个指南讲解详细到位,但对于像我这样没有 Go 基础的人来说,还有一些地方难以完全理解。希望作者能提供一些针对初学者学习 Go 的资源。

    有20位网友表示赞同!

眉黛如画

Protobuf生成go代码确实是件好事,但是这篇文章并没有解释清楚Go语言中如何使用这些生成的代码,仅仅是生成操作而已,对于实际应用的指导比较少。

    有19位网友表示赞同!

゛指尖的阳光丶

我以前觉得 protobuf 太复杂了,尤其是定义部分。看了这个指南以后感觉其实还好理解,关键在于掌握一些基本的语法规则。现在开始尝试用它来设计我的数据结构了!

    有17位网友表示赞同!

今非昔比'

很实用的一篇文章,讲解清晰,操作步骤也简单明了,我已经按照教程生成了 go 代码,并成功测试通过!强烈推荐给想要学习 Protobuf 的小伙伴们!

    有19位网友表示赞同!

慑人的傲气

终于不用再手动折腾代码了!这个指南简直太棒了,省时省力!以后可以专注于业务逻辑本身,而不是费时间去编写重复代码。

    有8位网友表示赞同!

我没有爱人i

虽然生成 Go 代码很容易实现,但在实际应用中需要考虑很多细节比如数据类型转换、错误处理等等。希望作者能在后续的博文中提供更深入的解析。

    有7位网友表示赞同!

热点资讯