google protobuf_protobuf 指南

4bc3c3c58a64102533a90dd60156396a.png
  • 简介
  • 安装
  • 语言定义
    • 特殊指令
    • 定义服务
    • JSON 支持
    • 选项
    • 生成代码
    • 基础类型
    • 更新 message
  • Golang 下使用
  • 参考

简介

Protocol Buffers 是 google 出品的一种数据交换格式, 缩写为 protobuf.

主要介绍 proto3 版本和 Golang 下的使用.

安装

protobuf 分为编译器和运行时两部分. 编译器直接使用预编译的二进制文件即可, 可以从 releases 上下载.

protobuf 运行时就是不同语言对应的库, 以 Golang 为例:

go get github.com/golang/protobuf/protoc-gen-go

语言定义

protobuf 现在有两个版本, proto2 和 proto3. 本着学新不学旧的原则, 这里只介绍 proto3.

既然是一种数据交换格式, 必然是要学习它的语法的, 就像学习 JSON 一样, 你总得知道如何定义.

默认的文件是 .proto.

下面是一个简单的例子, 来自于官方文档.

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

首行定义了语法版本, 即使用 proto3 版本. 然后定义了一个名为 SearchRequest 的 message, 以及它包含的字段(键值对). message 的结构非常类似于各种语言中的 struct, dict 或者 map.

每个字段包括三个部分, 类型, 字段名和字段编号. 前两个部分非常易懂, 主要解释一下字段编号. 在同一个 message 中字段编号应该是唯一的, 用于在 message 的二进制格式(message binary format)中标识字段. 因此数字的大小决定了编码的长度, 1-15 的数字只占用一个字节.

注释语法是 ///* ... */.

特殊指令

使用 reserved 注明已被废弃的字段编号和字段名称.

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

使用 repeated 可以指定重复字段, 即数组.

message Test4 {repeated int32 d = 4 [packed=true];
}

使用 enum 定义枚举类型. 每个枚举定义都必须包含一个映射值为 0 的常量作为第一个元素.

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;
}

定义枚举时, 可以使用 allow_alias 选项允许枚举值的别名.

enum EnumAllowingAlias {option allow_alias = true;UNKNOWN = 0;STARTED = 1;RUNNING = 1;  // RUNNING 是 STARTED 的别名
}

类型也可以嵌套使用.

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

使用 import 可以导入外部定义.

import "myproject/other_protos.proto";

使用 import public 可以传递导入依赖, 通常用于被导入的 proto 文件需要更改的情况下.

import public "new.proto";

protocol 编译器搜索的位置是命令行参数中的 -I/--proto_path flag. 如果没有提供, 则搜索编译器被调用时所在的目录.

Any 类型可以让你可以在没有它们的 proto 定义时, 将 messages 用作内嵌的类型. 一个 Any 包括任意的二进制序列化的 message, 就像 bytes 类型那样, 以及用作该类型的全局唯一的标识符 URL.

import "google/protobuf/any.proto";message ErrorStatus {string message = 1;repeated google.protobuf.Any details = 2;
}

默认的类型 URL 是 type.googleapis.com/packagename.messagename.

如果你有一个 message 包括许多字段, 但同时最多只有一个字段会被设置, 可以使用 Oneof 特性来节省内存. Oneof 字段和普通的字段没有区别, 除了所有这些 Oneof 字段共享内存, 且同时只能由一个字段被设置. 你可以使用特殊的 case()WhichOneof() 方法检查哪个字段被设置了, 具体方法名称取决于实现的语言.

message SampleMessage {oneof test_oneof {string name = 4;SubMessage sub_message = 9;}
}

可以在 Oneof 中添加任何类型的字段, 但不能使用 repeated.

使用 map 可以创建关联映射.

map<key_type, value_type> map_field = N;
map<string, Project> projects = 3;

key_type 可以是 integral 或 string 类型, 即 scalar 类型中除了 floating point types 和 bytes 以外的类型. value_type 可以是除 map 以外的任何类型.

使用 package 可以设置命名空间, 防止 message 类型冲突.

package foo.bar;
message Open { ... }

在另一个 proto 文件中使用.

message Foo {...foo.bar.Open open = 1;...
}

package 说明符会影响不同语言生成代码的方式:

  • Python: 忽略 package 指令
  • Golang: package 用作 Go 包名, 除了你使用 option go_package 显式声明包名

定义服务

如果你想要和 RPC 系统集成使用, 你可以定义 RPC 服务接口, 编译器会根据选择的语言, 生成对应的服务接口代码和存根.

service SearchService {rpc Search (SearchRequest) returns (SearchResponse);
}

最常见的是和 gRPC 一起使用.

JSON 支持

proto3 支持 JSON 中的规范编码, 具体的类型转换关系, 查看官方文档.

选项

有很多选项可以调节特性的行为, 完整的选项列表定义在 google/protobuf/descriptor.proto.

生成代码

要生成代码, 需要使用下面的命令, 对于 Golang 需要安装额外的插件.

protoc --proto_path=IMPORT_PATH --cpp_out=DST_DIR --java_out=DST_DIR --python_out=DST_DIR --go_out=DST_DIR --ruby_out=DST_DIR --objc_out=DST_DIR --csharp_out=DST_DIR path/to/file.proto

基础类型

标量值类型和各种语言间的转换可以参考 官方文档.

包括以下类型:

double
float
int32
int64
unit32
unit64
sint32  编码负数比 int32 更高效
sint64
fixed32 固定四字节. 如果数字通常大于 2^28, 比 uint32 更高效
fixed64
sfixed32 负数优化版本的 fixed32
sfixed64
bool
string
bytes

更新 message

官方指南翻译

  • 不要更改任何现有字段的字段编号.
  • 如果添加新的字段, 仍然可以使用新生成的代码解析旧的 message 格式. 但应该自行处理新加字段的默认值. 使用新代码创建的 message 也可以被旧代码解析, 那些新字段会被忽略.
  • 字段可以被删除, 只要不要复用那些字段编号. 要重命名字段, 可以给旧字段添加 OBSOLETE_ 前缀, 或者将字段编号设置为 reserved.
  • int32, uint32, int64, uint64, bool 是相互兼容的类型.
  • sint32 和 sint64 是相互兼容的, 但不兼容其他 int 类型.
  • string 和 bytes 可以是兼容的, 只要 bytes 是有效的 UTF-8.
  • 嵌入的 message 可以和 bytes 兼容, 如果 bytes 包含 message 的编码后的版本.
  • fixed32 和 sfixed32 兼容, fixed64 和 sfixed64 兼容.
  • enum 在 wire 格式上兼容 int32, uint32, int64, uint64(如果值不合适会被截断). 当 message 被反序列化时, 客户端代码可以用不同的方式对待它们. 比如, 未识别的 proto3 的 enum 类型将会保存在 message 中, 但它如何 表示是语言特定的. int 字段总是会保留它的值.
  • 将一个单个值更改为新 oneof 的成员是安全的且二进制兼容的. 移动多个字段到一个新的 oneof 可能是安全的, 如果你确保没有 code 被多次设置. 移动任何字段到一个已存在的 oneof 是不安全的.

Golang 下使用

定义 protobuf 文件 hello.proto 的内容为:

syntax = "proto3";import "google/protobuf/any.proto";package hello;
option go_package = "hello";message HelloReq {string name = 1;
}message HelloResp {int32 code = 1;string greet = 2;google.protobuf.Any details = 3;
}service HelloService {rpc Greet(HelloReq) returns (HelloResp);
}

初始化项目, 并生成文件:

go mod init tzh.com/app
go get github.com/golang/protobuf/protoc-gen-go
mkdir hello
# 假设 protoc3 已经解压好了
.protoc3binprotoc.exe  --proto_path=. --go_out=./hello hello.proto

main.go 如下:

package mainimport ("crypto/rand""fmt""github.com/golang/protobuf/proto""github.com/golang/protobuf/ptypes/any"hello "tzh.com/app/hello"
)func main() {req := &hello.HelloReq{Name: "hello",}details := make([]byte, 10)rand.Read(details)resp := &hello.HelloResp{Code:    1,Greet:   "hello name",Details: &any.Any{Value: details},}fmt.Println(req.String())fmt.Println(resp.String())// 序列化data, _ := proto.Marshal(req)fmt.Println(data)// 反序列化newReq := &hello.HelloReq{}proto.Unmarshal(data, newReq)fmt.Println(newReq)fmt.Println("text format", proto.MarshalTextString(req))}

如果你去看生成的代码, 会发现没有 HelloService 相关的内容, 这是因为没有使用 gRPC.

参考

  • github
  • go protobuf
  • proto3
  • Go Generated Code

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/532142.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机无法装补丁,电脑无法安装kb4012212补丁如何处理|电脑无法安装kb4012212补丁的处理方法...

最近&#xff0c;不少用户的电脑都被《永恒之蓝》病毒侵袭&#xff0c;因此微软官方推出了预防补丁 — kb4012212&#xff0c;正常系统只要安装该补丁就能避免电脑遭到伤害。不过&#xff0c;有用户反馈自己遇到了电脑无法安装kb4012212补丁的情况&#xff0c;该怎么办呢&#…

mysql在哪里写代码_[译] 如何写好 Go 代码

原文&#xff1a;https://scene-si.org/2018/07/24/writing-great-go-code/我写了多年的 Go 微服务&#xff0c;并在写完两本关于 (API Foundations in Go 和 12 Factor Applications with Docker and Go) 主题的书之后&#xff0c;有了一些关于如何写好 Go 代码的想法但首先&a…

学画画软件app推荐_路由器管理软件哪个好?6款路由器管理APP推荐_软件评测

无限网络应用越来越广泛&#xff0c;由此应运而生了许多可以蹭网的软件&#xff0c;家里的网速突然变慢了&#xff0c;也许就是隔壁的小哥哥小姐姐在蹭网络&#xff0c;那么如何避免被蹭网&#xff1f;今天小编给各位小伙伴推荐几款路由器管理软件&#xff0c;发现网络变慢了&a…

各个图标的意思_冬奥体育图标设计团队负责人林存真:每一个图标要画100稿以上...

林存真中央美术学院设计学院副院长、北京冬奥组委文化活动部形象景观艺术总监、北京冬奥会体育图标设计团队负责人。12月31日晚&#xff0c;北京2022年冬奥会和冬残奥会体育图标正式发布。在体育图标发布前夕&#xff0c;新京报记者采访了北京冬奥会体育图标设计团队的负责人&a…

delphi制作上下开幕效果_2019中超联赛揭幕战在深圳举行 现场开幕式亮点多多

3月2日晚&#xff0c;2019中超联赛开幕式在深圳大运中心体育场举行。随着中国足协党委书记杜兆才正式宣布2019年中超联赛开幕&#xff0c;以“超精彩”为口号的2019新赛季中超联赛正式打响。本赛季中超联赛是出台“注资帽”、“薪酬帽”、“奖金帽”、“转会帽”之后的第一个赛…

ae正在发生崩溃_AE错误:正在发生崩溃的解决方法,原创问题解决方案

AE在使用过程中,可能会出现一些问题。有的问题是莫名其妙出现。例如刚刚还在正常使用AE软件,下一次再打开的时候就会出现问题。今天给大家说的是如何去解决after effects错误:正在发生崩溃这个问题 。该问题所提供的解决方法为实际操作过,并成功解决。所以才写出来给大家提…

计算机二级公共,计算机二级公共基础知识

计算机二级公共基础知识计算机二级考试包括计算机基础知识。虽然分值不高但是我们还是要把握好每一分。下面百分网小编整理了相关计算机二级公共基础知识&#xff0c;希望大家喜欢。计算机二级公共基础知识1.1栈和队列1、栈及其基本运算栈是限定在一端进行插入与删除运算的线性…

echarts map 点击地图区域变色_绘制炫酷的地图,不只是pyecharts.map!

导读&#xff1a;地图可视化是一种非常直观的数据分析结果展现形式&#xff0c;python有很多可视化库可以实现&#xff0c;pyecharts就是很多python爱好者喜爱的实现地图可视化方法之一。不可否认&#xff0c;pyecharts绘制的地图实现方便、图形美观而且支持交互&#xff0c;但…

金蝶kis专业版公网访问_金蝶KIS云专业版—【账务处理】进阶操作101问

对KIS专业版【账务处理】模块日常操作之外的各种问题进行回答&#xff0c;帮助老师们快速进阶此模块的操作&#xff0c;提高软件的便利性。1.专业版资产负债表如何移动表页位置&#xff1f;【操作步骤】 1、单击【报表与分析】-【资产负债表】&#xff1b;2、单击左上角菜单栏【…

es集群搭建_滴滴Elasticsearch 集群跨版本升级与平台重构之路

前不久&#xff0c;滴滴ES团队将维护的30多个ES集群&#xff0c;3500多个ES节点&#xff0c;8PB的数据&#xff0c;从2.3.3跨大版本无缝升级到6.6.1。在对用户查询写入基本零影响和改动的前提下&#xff0c;解决了ES跨大版本协议不兼容、文件格式不兼容、mapping不兼容等难题&a…

电子工程可以报考二建_非工程类专业也能报考二建吗?

非工程类专业也能报考二建吗&#xff1f;2020年非工程类专业能考二级建造师的省份汇总整理&#xff01;2020年二级建造师考试报名公告陆续公布中&#xff0c;目前江西、陕西、江苏三省公布了报名时间&#xff0c;其他省份报名时间暂时未确定。四川省已经受疫情影响推迟五月的考…

计算机考试中英文打字题,计算机信息技术(五笔及中英文打字测试试题)

计算机信息技术(五笔及中英文打字测试试题) (14页)本资源提供全文预览&#xff0c;点击全文预览即可全文预览,如果喜欢文档就下载吧&#xff0c;查找使用更方便哦&#xff01;14.9 积分第一章基本知识习题答案一、填空题1. 计算机信息高新技术考试划分为五、四、三、二、_ 5个等…

pil python 安装_20行Python代码给微信头像戴帽子

作者 | Leauky&#xff0c;北理工硕士在读&#xff0c;非CS专业的Python爱好者。朋友圈里微信官方要求戴圣诞帽的活动曾经火爆一时&#xff0c;有些会玩的小伙伴都悄咪咪地用美图秀秀一类的 app 给自己头像 p 一顶&#xff0c;然后可高兴地表示“哎呀好神奇hhhh”&#xff0c;呆…

arcgis 属性表 汇总_Arcgis中遥感影像地理配准、矢量化与地图制作

目的&#xff1a;将遥感图像进行地理配准、矢量化&#xff0c;并且制作地图。要求&#xff1a;对的遥感图像进行地理配准&#xff1b;矢量化建筑物、绿地、道路、水体等主要地物要素&#xff1b;对各类地物要素进行符号化设置并对其名称进行标注&#xff1b;添加指北针、比例尺…

怎么查看计算机的系统内存大小,Windows10系统怎么查看电脑内存大小

很多用户在升级到windows10系统之后&#xff0c;因为很多界面和操作都跟之前的Windows系统不一样&#xff0c;所以很多操作都不知道要如何下手&#xff0c;比如想要查看电脑内存大小的时候却不知道要怎么操作&#xff0c;其实方法很简单&#xff0c;下面给大家介绍一下Windows1…

java类初始化顺序_《To Be a Better Javaer》-- Java 基础篇 vol.2:面向对象

Java是面向对象的高级编程语言&#xff0c;面向对象的特征如下&#xff1a;面向对象具有抽象、封装、继承、多态等特性&#xff1b;面向对象可以将复杂的业务逻辑简单化&#xff0c;增强代码复用性&#xff1b;面向对象是一种常见的思想&#xff0c;比较符合人们的思考习惯。面…

计算机开机时间停在上次关机,怎么在电脑开机的时候查看上次关机前的操作

满意答案wencai242013.09.05采纳率&#xff1a;51% 等级&#xff1a;12已帮助&#xff1a;12606人1.看计算机在哪天运行过~运行了多久!(系统安装在c盘)找到c:\windows\SchedLgU.txt文件 里面有你自这个系统产生以来曾经工作过的时间&#xff0c;包括哪天开了机 开机时间 关机…

php 递归实现无限极分类和排序_PHP实现选择排序

这次说说选择排序。 选择排序&#xff08;Selection sort&#xff09;是一种简单直观的排序算法。它的工作原理如下。首先在未排序序列中找到最小&#xff08;大&#xff09;元素&#xff0c;存放到排序序列的起始位置&#xff0c;然后&#xff0c;再从剩余未排序元素中继续寻找…

idea for循环快捷键_IDEA骚技巧,编码速度至少快一倍

IDEA是目前市场上最好用的IDE&#xff0c;公认的&#xff01;前几年eclipse在市场上非常流行&#xff0c;因此大多数人都习惯了eclipse的一些快捷键。近年来&#xff0c;随着IDEA的兴起&#xff0c;很多人都放弃了exlipse&#xff0c;进而选择了IDEA&#xff0c;但是有些人习惯…

从物联网到 3D 打印:硬件相关的开源项目概览 | 开源专题 No.52

arendst/Tasmota Stars: 20.4k License: GPL-3.0 Tasmota 是一款为 ESP8266 和 ESP32 设备提供的替代固件&#xff0c;具有易于配置的 webUI、OTA 更新、定时器或规则驱动的自动化功能以及通过 MQTT、HTTP、串口或 KNX 进行完全本地控制。该项目主要特点包括&#xff1a; 支持…