在proto中,可以使用OneOf类型,使用一个字段存储不同类型的数据。类似go中的interface。

假设有proto如下,Val是一个OneOf数据类型,它可以为double/int/str...中的任意一种。

TestPB中引用了value,类型为Val

syntax = "proto3";

package protooneof;
option go_package = "pb/message"; message Val{
oneof oneof_val {
double double = 1;
int64 int = 2;
string str = 3;
bytes bytes = 4;
uint64 uint = 5;
float float = 6;
}
} message TestPB {
Val value = 1;
}

赋值

编译这个proto,可以使用以下的代码对Val类型赋值:

	msg := &message.TestPB{
Value: &message.Val{
OneofVal: &message.Val_Str{Str: "hello"}, // 对oneof赋值需要使用Val包装,然后内部指定具体的类型
},
}

同理,使用=赋值也是可以的:

	msg.Value = &message.Val{
OneofVal: &message.Val_Float{Float: 123},
}

取值

假设知道值的类型,可以直接调用GetXXX方法取值。

	fv := msg.GetValue().GetStr()
fmt.Printf("fv:%v\n", fv) // 输出 hello

但是如果这个值未设置或者不存在,则会返回这个类型的0值

这就带来问题,如何判定这个值是否已设置,如果已设置是什么类型?

可以使用switch类型判定的方式来解决需求,因为已经穷举了Val所有可能的类型,如果未设置值,会打印未设置值

	switch v := msg.GetValue().GetOneofVal().(type) {
case *message.Val_Int:
fmt.Printf("int val:%v\n", v.Int)
case *message.Val_Float:
fmt.Printf("float val:%v\n", v.Float)
case *message.Val_Double:
fmt.Printf("double val:%v\n", v.Double)
case *message.Val_Str:
fmt.Printf("str val:%v\n", v.Str)
case *message.Val_Bytes:
fmt.Printf("bytes val:%v\n", v.Bytes)
case *message.Val_Uint:
fmt.Printf("uint val:%v\n", v.Uint)
default:
fmt.Printf("未设置值\n")
}

通过善用Oneof类型,可以让pb的结构更紧凑,满足更多元化的需求。

go: 在proto中使用oneof类型的更多相关文章

  1. Entity Framework 教程——Entity Framework中的实体类型

    Entity Framework中的实体类型 : 在之前的章节中我们介绍过从已有的数据库中创建EDM,它包含数据库中每个表所对应的实体.在EF 5.0/6.0中,存在POCO 实体和动态代理实体两种. ...

  2. Python中内置数据类型list,tuple,dict,set的区别和用法

    Python中内置数据类型list,tuple,dict,set的区别和用法 Python语言简洁明了,可以用较少的代码实现同样的功能.这其中Python的四个内置数据类型功不可没,他们即是list, ...

  3. 向mysql中插入Date类型的数据

    先看数据库表的定义 date字段为sql.date类型.我要向其中插入指定的日期和当前日期. 一.插入当前日期 思路:先获取当前系统,在将当前系统时间转换成sql类型的时间,然后插入数据库.代码如下 ...

  4. 在文件夹中 的指定类型文件中 查找字符串(CodeBlocks+GCC编译,控制台程序,仅能在Windows上运行)

    说明: 程序使用 io.h 中的 _findfirst 和 _findnext 函数遍历文件夹,故而程序只能在 Windows 下使用. 程序遍历当前文件夹,对其中的文件夹执行递归遍历.同时检查遍历到 ...

  5. Python 中的枚举类型~转

    Python 中的枚举类型 摘要: 枚举类型可以看作是一种标签或是一系列常量的集合,通常用于表示某些特定的有限集合,例如星期.月份.状态等. 枚举类型可以看作是一种标签或是一系列常量的集合,通常用于表 ...

  6. UNIX中的文件类型

    Unix的文件类型信息包含在stat结构的st_mode成员中可以用宏确定文件类型: 普通文件(S_ISREG()):包含某种形式数据的常用文件类型 目录文件(S_ISDIR()):这种文件包含其他文 ...

  7. 命名空间“System.Web”中不存在类型或命名空间名称“Optimization”(是否缺少程序集引用?)

    今天,在.net4.5,mvc4下新建了个区域,运行起来就报这个错误: 命名空间"System.Web"中不存在类型或命名空间名称"Optimization"( ...

  8. C#解决一个奇怪的,命名空间“XXX”中不存在类型或命名空间名称“xxx”的问题

    最近做项目时,引用了一个第三方的程序集,代码层面没有任何语法错误,编译提示:命名空间"System.Net"中不存在类型或命名空间名称"FtpClient".是 ...

  9. [delphi]向ImageList中加入png类型的资源图片

    向ImageList中动态加入Png图片有些失真,经过多方查询,发现需要将Bitmap的AlphaFormat指定一下. //向ImageList中加入png类型的资源图片 procedure Add ...

  10. 在 Typescript 2.0 中使用 @types 类型定义

    在 Typescript 2.0 中使用 @type 类型定义 基于 Typescript 开发的时候,很麻烦的一个问题就是类型定义.导致在编译的时候,经常会看到一连串的找不到类型的提示.解决的方式经 ...

随机推荐

  1. 【EF Core】自动生成的字段值

    自动生成字段值,咱们首先想到的是主键列(带 IDENTITY 的主键).EF Core 默认的主键配置也是启用 Identity 自增长的,而且可以自动标识主键.前提是代表主键的实体属性名要符合以下规 ...

  2. [SDOI2012] 走迷宫 题解

    前言 题目链接:洛谷:Hydro & bzoj. 题意简述 有向图中,求起点到终点的期望步数.若期望不存在,输出 INF. 保证强连通分量的大小不超过 \(100\). 题目分析 首先来想想什 ...

  3. Lazysysadmin靶机笔记

    Lazysysadmin靶机笔记 概述 lazysysadmin是一台Vulnhub靶机,整体比较简单. 靶机地址:https://pan.baidu.com/s/19nBjhMpGkdBDBFSnM ...

  4. 一步步开发Windows服务(Windows Service)[转]

    基于0起步来创建一个服务,做到简单的记录时间日志功能,其具体招行方法可自行添加. 1.创建服务 2.删除默认服务文件 3.添加自己的服务文件 4.更改启动项目 5. 引用 using System.T ...

  5. tomcat发布两个项目报错webAppKey重复设置

    两个项目的web.xml中都有一个日志监听器配置 <listener> <listener-class> org.springframework.web.util.Log4jC ...

  6. [SHOI2009] 会场预约 题解

    LG2161 显然: 任意时刻每个点最多被一条线段覆盖 暴力删每条线段的复杂度是对的 插入 \([l,r]\) 时需要删除的线段要么被 \([l,r]\) 包含,要么覆盖 \(l\) 或 \(r\) ...

  7. 使用Kiota工具生成WebApi的代理类,以及接口调用的简单体验

    前言 当前.NET环境下,生成WebApi代理类的工具已经有很多选择了,比如OpenApi Generator,NSwag和Refitter等,不同的工具生成的代码风格以及实现方式略有不同,比如Ref ...

  8. JAVA——instanceof运算符(问题待处理)

    2024/07/12 1.问题 2.问题拆解 3.解决 1.问题 今天学了一个运算符--instanceof,概念很抽象,感觉暂时理解不了,什么实例对象.类.子类,看得迷迷糊糊的,先记录下来,有空做一 ...

  9. Ubuntu16.04使用命令行安装jdk1.8

    在Ubuntu中安装jdk过于麻烦,有时设置不好可能就没有办法使用,卸载也难以卸载干净,所以这篇文章使用相对简单的命令行来安装jdk,只需简单的四个命令,省去许多麻烦,下面是方法. 进入Ubuntu打 ...

  10. Homebrew 卸载 Wireshark 报错

    我在使用 Homebrew 安装 Wireshark 的时候,Homebrew 要求我输入密码.此时我又不想安转 Wireshark 了,于是我没有输入密码并且按下了 Ctrl + C.后来,我又尝试 ...