protocol buffer没那么难,不信你看这篇

2024-02-24 15:58
文章标签 protocol 这篇 buffer 不信

本文主要是介绍protocol buffer没那么难,不信你看这篇,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 简介
  • 定义一个消息
    • 类型定义
    • 字段的值
    • 字段描述符
    • 添加注释
  • 嵌套类型
  • Map
  • 总结

简介

上一篇文章我们对google的protobuf已经有了一个基本的认识,并且能够使用相应的工具生成对应的代码了。但是对于.proto文件的格式和具体支持的类型还不是很清楚。今天本文将会带大家一探究竟。

注意,本文介绍的协议是proto3版本的。

定义一个消息

protobuf中的主体被称为是message,可以将其看做是我们在程序中定义的类。我们可以在.proto文件中定义这个message对象,并且为其添加属性,如下所示:

syntax = "proto3";message SearchRequest {string query = 1;int32 page_number = 2;int32 result_per_page = 3;
}

上例的第一行指定了.proto文件的协议类型,这里使用的是proto3,也是最新版的协议,如果不指定,默认情况下是proto2。

类型定义

这里我们为SearchRequest对象,定义了三个属性,其类型分别是String和int32。

String和int32都是简单类型,protobuf支持的简单类型如下:

protobuf类型说明对应的java类型
double双精度浮点类型double
float浮点类型float
int32整型数字,最好不表示负数int
int64整型数字,最好不表示负数long
uint32无符号整数int
uint64无符号整数long
sint32带符号整数int
sint64带符号整数long
fixed32四个字节的整数int
fixed648个字节的整数long
sfixed324个字节的带符号整数int
sfixed648个字节的带符号整数long
bool布尔类型boolean
string字符串String
bytes字节ByteString

当然protobuf还支持复杂的组合类型和枚举类型。

枚举类型在protobuf中用enum来表示,我们来看一个枚举类型的定义:

message SearchRequest {string query = 1;int32 page_number = 2;int32 result_per_page = 3;enum Corpus {UNIVERSAL = 0;WEB = 1;IMAGES = 2;LOCAL = 3;NEWS = 4;PRODUCTS = 5;VIDEO = 6;}Corpus corpus = 4;
}

上面我们定义了一个枚举类型Corpus,枚举类型中定义的枚举值是从0开始的,0也是枚举类型的默认值。

在枚举中,还可以定义具有相同value的枚举类型,但是这样需要加上allow_alias=true的选项,如下所示:

message MyMessage1 {enum EnumAllowingAlias {option allow_alias = true;UNKNOWN = 0;STARTED = 1;RUNNING = 1;}
}
message MyMessage2 {enum EnumNotAllowingAlias {UNKNOWN = 0;STARTED = 1;// RUNNING = 1;  // Uncommenting this line will cause a compile error inside Google and a warning message outside.}
}

在枚举类型中,如果我们后续对某些枚举类型进行了删除,那么被删除的值可能会被后续的用户使用,这样就会造成潜在的代码隐患,为了解决这个问题,枚举提供了一个reserved的关键词,被这个关键词声明的枚举类型,就不会被后续使用,如下所示:

enum Foo {reserved 2, 15, 9 to 11, 40 to max;reserved "FOO", "BAR";
}

reserved关键字也可以用在message的字段中,表示后续不要使用到这些字段,如下:

message Foo {reserved 2, 15, 9 to 11;reserved "foo", "bar";
}

字段的值

我们可以看到,每个message的字段都分配了一个值,每个字段的值在message中都是唯一的,这些值是用来定位在二进制消息格式中的字段位置。所以一旦定义之后,不要随意修改。

要注意的是值1-15在二进制中使用的1个字节来表示的,值16-2047需要使用2个字节来表示,所以通常将1-15使用在最常见的字段和可能重复的字段,这样可以节约编码后的空间。

最小的值是1,最大的值是2的29次方-1,或者536,870,911。这中间从19000-19999是保留数字,不能使用。

当消息被编译之后,各个字段将会被转成为对应的类型,并且各个字段类型将会被赋予不同的初始值。

strings的默认值是空字符串,bytes的默认值是空bytes,bools的默认值是false,数字类型的默认值是0,枚举类型的默认值是枚举的第一个元素。

字段描述符

每个消息的字段都可以有两种描述符,第一种叫做singular,表示message中可以有0个或者1个这个字段,这是proto3中默认的定义方式。

第二种叫做repeated,表示这个字段在message中是可以重复的,也就是说它代表的是一个集合。

添加注释

在proto中的注释和C++的风格类似,可以使用: // 或者 /* … */ 的风格来注释,如下所示:

/* 这是一个注释. */message SearchRequest {string query = 1;int32 page_number = 2;  // 页面的numberint32 result_per_page = 3;  // 每页的结果
}

嵌套类型

在一个message中还可以嵌入一个message,如下所示:

message SearchResponse {message Result {string url = 1;string title = 2;repeated string snippets = 3;}repeated Result results = 1;
}

在上例中,我们在SearchResponse定义了一个Result类型,在java中,实际上可以将其看做是嵌套类。

如果希望在message的定义类之外使用这个内部的message,则可以通过_Parent_._Type_来定义:

message SomeOtherMessage {SearchResponse.Result result = 1;
}

嵌套类型可以任意嵌套,如下所示:

message Outer {                  // Level 0message MiddleAA {  // Level 1message Inner {   // Level 2int64 ival = 1;bool  booly = 2;}}message MiddleBB {  // Level 1message Inner {   // Level 2int32 ival = 1;bool  booly = 2;}}
}

Map

如果想要在proto中定义map,可以这样写:

map<key_type, value_type> map_field = N;

这里的value_type可以是除map之外的任意类型。注意map不能是repeated。

map中的数据的顺序是不定的,我们不能依赖存入的map顺序来判断其取出的顺序。

总结

以上就是proto3中定义声明文件该注意的事项了,大家在使用protobuf的时候要多加注意。

本文已收录于 http://www.flydean.com/02-protocolbuf-detail/

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!

这篇关于protocol buffer没那么难,不信你看这篇的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/742602

相关文章

Go语言使用Buffer实现高性能处理字节和字符

《Go语言使用Buffer实现高性能处理字节和字符》在Go中,bytes.Buffer是一个非常高效的类型,用于处理字节数据的读写操作,本文将详细介绍一下如何使用Buffer实现高性能处理字节和... 目录1. bytes.Buffer 的基本用法1.1. 创建和初始化 Buffer1.2. 使用 Writ

Java 文件读写最好是用buffer对于大文件可以加快速度

参考例子: FileReader fileReader = new FileReader(filename);BufferedReader bufferedReader = new BufferedReader(fileReader);List<String> lines = new ArrayList<String>();String line = null;while ((line =

【Node】Buffer 与 Stream

node 为什么会出现 Buffer 这个模块 在最初的时候,JavaScript 只运行在浏览器端, 对于处理 Unicode 编码的字符串很容易,但是对于处理二进制以及非 Unicode 编码的数据便无能为力。 不过对于 Server 端操作来说 网络I/O 以及 文件I/O 的处理是必须的,所以 Node 中便提供了 Buffer 类处理二进制的数据。 二进制缓冲区 Buffer

【0324】Postgres内核 Shared Buffer Access Rules (共享缓冲区访问规则)说明

0. 章节内容 1. 共享磁盘缓冲区访问机制 (shared disk buffers) 共享磁盘缓冲区有两套独立的访问控制机制:引用计数(a/k/a pin 计数)和缓冲区内容锁。(实际上,还有第三级访问控制:在访问任何属于某个关系表的页面之前,必须持有该关系表的适当类型的锁。这里不讨论关系级锁。) Pins 在对缓冲区做任何操作之前,必须“对缓冲区pin”(即增加其引用计数, re

Netty源码解析1-Buffer

大数据成神之路系列: 请戳GitHub原文: https://github.com/wangzhiwubigdata/God-Of-BigData 上一篇文章我们概要介绍了Netty的原理及结构,下面几篇文章我们开始对Netty的各个模块进行比较详细的分析。Netty的结构最底层是buffer机制,这部分也相对独立,我们就先从buffer讲起。 What:buffer简介 buffer中文

神仙级AI大模型入门教程(非常详细),从零基础入门到精通,从看这篇开始!

一.初聊大模型 1.为什么要学习大模型? 在学习大模型之前,你不必担心自己缺乏相关知识或认为这太难。我坚信,只要你有学习的意愿并付出努力,你就能够掌握大模型,并能够用它们完成许多有意义的事情。在这个快速变化的时代,虽然新技术和概念不断涌现,但希望你能静下心来,踏实地学习。一旦你精通了某项技术,你就能够用它来实现自己的目标,甚至可能找到理想的工作或完成具有挑战性的项目。 在众多的技术中,大模型

WebDriver与Chrome DevTools Protocol:如何在浏览器自动化中提升效率

介绍 随着互联网数据的爆炸式增长,爬虫技术成为了获取信息的重要工具。在实际应用中,如何提升浏览器自动化的效率是开发者常常面临的挑战。Chrome DevTools Protocol(CDP)与Selenium WebDriver相结合,为浏览器自动化提供了强大的控制能力,并允许用户直接与浏览器的底层交互。本文将通过使用CDP优化Selenium的效率,结合代理IP技术,实现对微博数据的高效采

Pencils Protocol生态新进展,即将上线 Vault 产品

“极高的盈利预期、通证的持续回购与销毁,Vault产品的推出正在成为Pencils Protocol生态发展的重磅利好。” Pencils Protocol是目前Scroll生态TVL最高的DeFi平台 ,即便是行情整体较为平淡,其仍旧能够保持在3亿美元左右的锁仓价值,并拥有超过247,000名活跃用户。 而进入到9月,Pencils Protocol陆续迎来了

【LINUX】“dmesg: read kernel buffer failed: Operation not permitted“ 错误

出现 “dmesg: read kernel buffer failed: Operation not permitted” 错误通常是因为当前用户没有权限读取内核日志缓冲区 这可以通过修改内核参数 kernel.dmesg_restrict 来解决。 你可以尝试以下命令来允许非特权用户读取内核日志: sudo sysctl -w kernel.dmesg_restrict=0 这个命令

技术干货 |如何保障 IM以及音视频的系统稳定性、安全性、可靠性?看这篇就懂!

在当今快节奏的商业环境下,to B 行业客户对产品质量的要求越来越高,尤其是对于 IM 及音视频服务端稳定性的要求更加突出。随着技术的不断进步,这些服务的使用量不断攀升,因此稳定性建设显得尤为重要。从技术角度上,需要重视系统性能、可靠性、安全性等方面的提升,在流程上需要建立完善的开发、测试、部署流程,以确保服务端稳定性的提高。同时,需要加强对于系统监控、故障排查、灾备恢复等方面的投入,避免服务中断