首页 > 其他分享 >Protocol Buffers 3 语法

Protocol Buffers 3 语法

时间:2023-06-08 10:45:29浏览次数:50  
标签:pb Protocol string proto 语法 编号 go message Buffers

Protocol Buffers 3 语法

标签(空格分隔): protocol buffers

本主题介绍如何在项目中使用协议缓冲区版本 3
官网地址:https://protobuf.dev/programming-guides/proto3/

定义消息类型

首先,让我们看一个非常简单的例子。假设您要定义一种搜索请求消息格式,其中每个搜索请求都有一个查询字符串、您感兴趣的特定结果页面以及每页的结果数。下面是用于定义消息类型的 .proto 文件

syntax = "proto3";

message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 results_per_page = 3;
}
  1. 文件的第一行指定您正在使用 proto3 语法:如果您不这样做,协议缓冲区编译器将假定您使用的是 proto2。这必须是文件的第一个非空、非注释行
  2. SearchRequest 消息定义指定三个字段(名称/值对),每个字段对应要包含在此类消息中的每条数据。每个字段都有名称和类型

指定字段类型

在前面的示例中,所有字段都是标量类型:两个整数(page_number 和 results_per_page)和一个字符串(查询)。您还可以指定枚举和复合类型,例如字段的其他消息类型

  1. 标量类型官网地址:https://protobuf.dev/programming-guides/proto3/#scalar
    double float int32 int64 uint32 uint64 sint32 sint64 bool string bytes

  2. 枚举类型:

    enum Corpus {
    CORPUS_UNSPECIFIED = 0; // 枚举类型的编号必须是零开始
    CORPUS_UNIVERSAL = 1;
    CORPUS_WEB = 2;
    CORPUS_IMAGES = 3;
    CORPUS_LOCAL = 4;
    CORPUS_NEWS = 5;
    CORPUS_PRODUCTS = 6;
    CORPUS_VIDEO = 7;
    }

    message SearchRequest {
    string query = 1;
    int32 page_number = 2;
    int32 results_per_page = 3;
    Corpus corpus = 4;
    }
    3.其他类型

类型默认值

对于字符串,默认值为空字符串。
对于字节,默认值为空字节。
对于布尔值,默认值为 false。
对于数值类型,默认值为零。
对于枚举,默认值是第一个定义的枚举值,必须为 0。
对于消息字段,未设置该字段。它的确切值取决于语言。有关详细信息,请参阅生成的代码指南

分配字段编号

必须为消息定义中的每个字段指定一个介于 1 和 536,870,911 之间的数字,并具有以下限制

  1. 给定的数字在该消息的所有字段中必须是唯一的。
  2. 字段编号 19,000 到 19,999 保留用于协议缓冲区实现。如果在消息中使用这些保留字段编号之一,协议缓冲区编译器将进行投诉。
  3. 不能使用任何以前保留的字段编号或已分配给扩展的任何字段编号。

使用消息类型后,无法更改此数字,因为它标识消息线格式的字段。“更改”字段编号等效于删除该字段并创建一个类型相同但新编号的新字段。有关如何正确执行此操作,请参阅删除字段

切勿重复使用字段编号。切勿从保留列表中取出字段编号,以便在新字段定义中重复使用。请参阅重用字段编号的后果。

对于最常设置的字段,应使用字段编号 1 到 15。较低的字段编号值在导线格式中占用的空间较少。例如,范围为 1 到 15 的字段编号需要一个字节进行编码。16 到 2047 范围内的字段编号需要两个字节。您可以在协议缓冲区编码中找到有关此内容的更多信息

指定字段标签

消息字段可以是以下字段之一
  • optional 可选:可选字段处于以下两种可能状态之一:

    • 该字段已设置
    • 该字段未设置
  • repeated 重复:此字段类型可以在格式正确的消息中重复零次或多次。将保留重复值的顺序

  • map 映射:这是成对的键/值字段类型。有关此字段类型的详细信息,请参阅地图

     message Test6 {
       map<string, int32> g = 7;
     }
     
     message Test6 {
       message g_Entry {
         optional string key = 1;
         optional int32 value = 2;
       }
       repeated g_Entry g = 7;
     }
    

文件示例

// 选中语法格式proto3,也就是ProtocolBuffer的版本3
syntax = "proto3";

// 定义包名
package proto.v1;
// go语言的包路径
option go_package="go-example/grpc/proto;example_pb";

//

// 引入官方包
import "google/protobuf/empty.proto";
import "google/protobuf/timestamp.proto";

// 同级目录导入
import "base.proto";
// 引入不同目录的proto文件 目前我还没研究明白

// 1. 官方proto生成例子:会生成两个pb文件 pb.go && grpc.pb.go
// protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative ./example.proto

// 2. 生成到一个pb文件:生成到go_package的位置
// protoc --go_out=plugins=grpc:.  ./example.proto
// 3. 生成到一个pb文件: 生成到当前目录
// protoc --go_out=plugins=grpc:. --go_opt=paths=source_relative ./example.proto

// 枚举类型:编号必须是0开始
enum HouseStatus {
  HOUSE_STATUS_0 = 0;
  HOUSE_STATUS_1 = 1;
  HOUSE_STATUS_2 = 2;
}

// 用户实体
message UserEntity {
  string id = 1;
  string username =2;
  string avatar = 3;
  int64 loginAt = 4;
}

message GetUserRequest {
  // 引入同级目录
  Page page = 8;
  // 多个data 并且 message 嵌套
  repeated UserEntity data = 7;
  message Where {
    string phone = 1;
    string platform = 2;
  }
  // 枚举
  HouseStatus status = 1;
  // 使用其他包的message
  google.protobuf.Empty empty = 4;
  // map
  map<string, string> mp = 5;
  // 使用其他包message
  google.protobuf.Timestamp addTime = 6;
}

message GetUserInfoRequest {

}

service UserService {
  // 一元
  rpc GetUserInfoOne(GetUserInfoRequest) returns (UserEntity);
  // 服务端流
  rpc GetUserInfoTwo(GetUserInfoRequest) returns (stream UserEntity);
  // 客户端流
  rpc GetUserInfoThree(stream GetUserInfoRequest) returns (UserEntity);
  // 双向流
  rpc GetUserInfoFour(stream GetUserInfoRequest) returns (stream UserEntity);
}

对比Proto和Json编码

package main

import (
	"encoding/json"
	"fmt"
	"github.com/golang/protobuf/proto"
	example_pb "go-example/grpc/proto"
	"google.golang.org/protobuf/types/known/timestamppb"
)

func main() {

	userRequest := example_pb.GetUserRequest{
		Page: &example_pb.Page{
			Page:  1,
			Limit: 10,
			Count: 100,
		},
		Status: example_pb.HouseStatus_HOUSE_STATUS_0,
		Empty:  nil,
		Mp: map[string]string{
			"hello": "world",
		},
		AddTime: timestamppb.Now(),
	}
	// 对比proto和json
	// proto 编码
	marshal, err := proto.Marshal(&userRequest)
	if err != nil {
		panic(err)
	}
	fmt.Printf("proto: %+v\n", marshal)

	// json编码
	jsonMarshal, err := json.Marshal(&userRequest)
	if err != nil {
		panic(err)
	}
	fmt.Printf("json: %+v\n", jsonMarshal)
}

标签:pb,Protocol,string,proto,语法,编号,go,message,Buffers
From: https://www.cnblogs.com/yanweifeng/p/17465496.html

相关文章

  • 微信小程序中的基础语法
    微信小程序中的基础语法微信小程序是一种轻量级的应用程序,它具有简单、高效、易用等特点。在学习微信小程序开发的过程中,了解其基础语法非常重要。本文将介绍微信小程序中的基础语法。1.WXMLWXML是微信小程序的模板语言,类似于HTML。WXML与HTML的语法很相似,但是WXML更加轻量级,支持......
  • 动态组件,插槽,vue-cli创建项目,目录结构,编写规范,导入导出语法
    1动态组件#<component:is="who"></component>#component标签的is属性等于组件名字,这里就会显示这个组件<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>Title</title>......
  • vue之vue-cli创建项目、vue项目目录结构、vue项目编写规范、 es6导入导出语法
    目录一、vue-cli创建项目1.1、背景知识单页面应用:spa单文件组件(一个组件一个文件)一个组件中有的东西使用vue-cli创建vue项目,才能使用单文件组件vue-cli脚手架,1.2使用vue-cli创建vue项目1.3vue-cli创建项目vue-cli命令行创建项目使用vue-cli-ui创建运行vue项目方式一:命令行中......
  • JS基础语法(一)
    javascript简介javascrpit是是一种轻量级的编程语言,常用于web前端开发。另外js还可以用来写node.js类型的服务和工具,在测试web项目的时候需要了解。  变量js定义变量有3种方式:var、const、let,3者的区别:在2015年以前,使用var关键字来声明JavaScript变量。在2015后......
  • 8、hive的关系运算、逻辑预算、数学运算、数值运算、日期函数、条件函数和字符串函数
    ApacheHive系列文章1、apache-hive-3.1.2简介及部署(三种部署方式-内嵌模式、本地模式和远程模式)及验证详解2、hive相关概念详解--架构、读写文件机制、数据存储3、hive的使用示例详解-建表、数据类型详解、内部外部表、分区表、分桶表4、hive的使用示例详解-事务表、视图、物......
  • 关于青语言语法设计的讨论
    数心开物工作室于6月1日开源发布了一门中文编程语言——青语言,并在开源中国、博客园等技术社区发布了相关新闻。与预期的一样,中文编程作为一个极具争议性的话题,该新闻一经发布,便收获了较多的关注和评论,其中包括大量的差评,甚至恶评。作为一个开源项目,我们并不介意这样的讨论,也不热......
  • C#基础语法_2
    1、命名规范首先要保证变量名要有意义。 1)、现阶段给变量起名都以字母开头 2)、后面可以跟任意字母、数字、下划线注意: 1)、变量名不要与C#系统的关键字重复 2)、在C#中,大小写敏感  3)、同一个变量名不允许重复定义(不严谨)给变量起名要满足两个命名规范 1)、Camel......
  • C语言编程语法—文件读写
    一个文件,无论它是文本文件还是二进制文件,都是代表了一系列的字节。C语言不仅提供了访问顶层的函数,也提供了底层(OS)调用来处理存储设备上的文件。本章将讲解文件管理的重要调用。打开文件您可以使用fopen()函数来创建一个新的文件或者打开一个已有的文件,这个调用会初始化类型FIL......
  • linux shell if else 多个选择条件的判断语句 语法
    该脚本为,如果满足i等于mysql、information_schema、performance_schema、db_sys_stat其中一个那么就跳出执行下面的。重点介绍:if条件语句[]左右两个都要有一个空格。#!/bin/bash#2012-12-25bycocoforiin`cat./db_list.txt`doif["$i"=="mysql"]||["$i"==......
  • mysql select into outfile 语法 乱码问题
    一个常见的问题,mysql导出csv格式的语法,已经乱码问题:由于数据库一般默认的是UTF-8格式的字符集,而execl默认的是gbk格式的字符集,这里有两种方法解决乱码:方法一:先转出.txt格式的文件,然后选择用excel打开时,提示选择哪种编码打开,选择gbk即可select*frommobile_order_regionwhere......