当前位置: 首页 > news >正文

通过protoc工具生成proto的pb.go文件以及使用protoc-go-inject-tag工具注入自定义标签

1.ProtoBuf认识,安装以及用法

参考:[golang 微服务] 3. ProtoBuf认识,安装以及golang 中ProtoBuf使用

2. 使用protoc-go-inject-tag工具注入自定义标签

这里有一个案例:

syntax=proto3;
package test;option go_package = ".;test";message MyMessage {int64 Code = 1;
}

执行protoc --proto_path=. --go_out=. test.proto导出的test.pb.go里的MyMessage这个结构体的定义会是这样:

type MyMessage struct {state         protoimpl.MessageStatesizeCache     protoimpl.SizeCacheunknownFields protoimpl.UnknownFieldsCode int64 `protobuf:"varint,1,opt,name=Code,proto3" json:"Code,omitempty"`
}

可以看到Code字段的protobuf和json的tag都是固定的(目前还没有找到方法能通过protoc命令的参数来设置tag),但是这样的struct有时候并不是我们所期待的,比如下面的代码片段:

msg := &MyMessage{Code: 0}
bdata, _ := json.Marshal(msg)
fmt.Println(string(bdata))

这段代码最终的输出会是{},因为Code的json tag设置了omitempty,这种情况在开发过程中有时候是很蛋疼的,因为即便Code是默认值0,我们也还是希望能打印出来的。因此我们需要一种方法能通过在编写proto文件的时候,在里面注入tag,然后导出成go的时候这个被注入的字段的tag可以自定义。

这时,就可以使用protoc-go-inject-tag工具了, 这个库可以在proto文件中注入tag,然后在导出的时候相应的字段的tag就可以被修改掉了,,步骤如下:

(1).proto-go-inject-tag工具介绍

protoc-go-inject-tag 是一个用于在生成的 Go 结构体中注入自定义标签的工具。在使用 Protocol Buffers(protobuf)生成 Go 代码时,默认情况下生成的.go文件里的结构体标签是没办法灵活设置的。protoc-go-inject-tag 工具允许开发者在生成的 Go 文件中注入自定义的标签,从而提高代码的灵活性和可维护性

(2).下载并安装protoc-go-inject-tag

首先,确保已经安装了 protoc 和 protoc-gen-go,然后安装 protoc-go-inject-tag

go install github.com/favadi/protoc-go-inject-tag@latest

(3)..proto文件创建

这里举个例子: agent.proto文件部分原始代码如下:

syntax = "proto3";
package agent.pb;// 代理数据-统计日报
option go_package = "agent/proto/agentpb";//分组成员(组,成员)详细代理数据model Body
message GroupDetailDataModelBody{repeated GroupDetailDataModel list = 1;
}//获取分组成员(组长,成员)对应的代理相关数据
//分组成员(组,成员)详细代理数据model
message GroupDetailDataModel{uint64 id = 1; // 组id(group_id)/成员id(manager_id)string name = 2;  // 名称uint64 new_agent_num = 3; // 新增代理人数uint64 effect_agent_num = 4; // 有效新增代理人数: exp > 0的人数uint64 exp = 5; // 代理充值金额bool is_group = 6; //  当is_group为false时,id表示成员id(也就是manager_id),点击"详情"时,访问的是daily/detailAccount接口; 当is_group为true时,id表示组id(也就是group_id), 点击"详情"时,访问的是daily/detailGroup接口
}

(4).生成.pb.go文件

cd 到proto文件下面,执行下面命令即可:

protoc --go_out=./ agent.proto  //一般情况下使用这个命令
protoc --go_out=plugins=grpc:. agent.proto  //有RPC服务的情况下使用这个命令

(5).查看.pb.go文件

通过protoc --go_out 生成的agent.pb.go部分结构体如下:

// 获取分组成员(组长,成员)对应的代理相关数据
// 分组成员(组,成员)详细代理数据model
type GroupDetailDataModel struct {state         protoimpl.MessageStatesizeCache     protoimpl.SizeCacheunknownFields protoimpl.UnknownFieldsId uint64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` // 组id(group_id)/成员id(manager_id)Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` // 名称NewAgentNum uint64 `protobuf:"varint,3,opt,name=new_agent_num,json=newAgentNum,proto3" json:"new_agent_num,omitempty"` // 新增代理人数EffectAgentNum uint64 `protobuf:"varint,4,opt,name=effect_agent_num,json=effectAgentNum,proto3" json:"effect_agent_num,omitempty"` // 有效新增代理人数: exp > 0的人数Exp uint64 `protobuf:"varint,5,opt,name=exp,proto3" json:"exp,omitempty"` // 代理充值金额IsGroup bool `protobuf:"varint,6,opt,name=is_group,json=isGroup,proto3" json:"is_group,omitempty"` //  当is_group为false时,id表示成员id(也就是manager_id),点击"详情"时,访问的是daily/detailAccount接口; 当is_group为true时,id表示组id(也就是group_id), 点击"详情"时,访问的是daily/detailGroup接口
}

上述结构体中,json格式中的omitempty表示:如果该属性没有值,则不会显示,也就是说,当对应属性为nil或者没有赋值时,不会返回给前端接口

但是,有时候,却需要返回给前端接口对应的值,不论其值是否存在,这里就需要使用protoc-go-inject-tag工具来自定义标签了,操作如下步骤

(5).使用protoc-go-inject-tag工具注入自定义标签

首先,需要修改proto代码,自定义标签使用语法如下:  // @gotags: json:"属性名", 通过设置,然后通过protoc-go-inject-tag -input=./xxx.pb.go 就可以自定义设置属性标签了,修改proto文件如下:

syntax = "proto3";
package agent.pb;// 代理数据-统计日报
option go_package = "agent/proto/agentpb";message GroupDetailDataModelBody{// @gotags: json:"list"repeated GroupDetailDataModel list = 1;
}//获取分组成员(组长,成员)对应的代理相关数据
//分组成员(组,成员)详细代理数据model
message GroupDetailDataModel{// @gotags: json:"id"uint64 id = 1; // 组id(group_id)/成员id(manager_id)// @gotags: json:"name"string name = 2;  // 名称// @gotags: json:"new_agent_num"uint64 new_agent_num = 3; // 新增代理人数// @gotags: json:"effect_agent_num"uint64 effect_agent_num = 4; // 有效新增代理人数: exp > 0的人数// @gotags: json:"exp"uint64 exp = 5; // 代理充值金额// @gotags: json:"is_group"bool is_group = 6; //  当is_group为false时,id表示成员id(也就是manager_id),点击"详情"时,访问的是daily/detailAccount接口; 当is_group为true时,id表示组id(也就是group_id), 点击"详情"时,访问的是daily/detailGroup接口
}

上面自定义对应的属性标签,json中只有对应的属性,去掉了 omitempty,也就是说:不论对应的属性是否有值,其属性名称都应该返回,没有值时返回的是默认值

通过protoc-go-inject-tag -input=命令注入自定义标签修该.pb.go文件如下:

protoc-go-inject-tag -input=./agent.pb.go

修改后的.pb.go部分代码如下:

// 分组成员(组,成员)详细代理数据model
type GroupDetailDataModel struct {state         protoimpl.MessageStatesizeCache     protoimpl.SizeCacheunknownFields protoimpl.UnknownFields// @gotags: json:"id"Id uint64 `protobuf:"varint,1,opt,name=id,proto3" json:"id"` // 组id(group_id)/成员id(manager_id)// @gotags: json:"name"Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name"` // 名称// @gotags: json:"new_agent_num"NewAgentNum uint64 `protobuf:"varint,3,opt,name=new_agent_num,json=newAgentNum,proto3" json:"new_agent_num"` // 新增代理人数// @gotags: json:"effect_agent_num"EffectAgentNum uint64 `protobuf:"varint,4,opt,name=effect_agent_num,json=effectAgentNum,proto3" json:"effect_agent_num"` // 有效新增代理人数: exp > 0的人数// @gotags: json:"exp"Exp uint64 `protobuf:"varint,5,opt,name=exp,proto3" json:"exp"` // 代理充值金额// @gotags: json:"is_group"IsGroup bool `protobuf:"varint,6,opt,name=is_group,json=isGroup,proto3" json:"is_group"` //  当is_group为false时,id表示成员id(也就是manager_id),点击"详情"时,访问的是daily/detailAccount接口; 当is_group为true时,id表示组id(也就是group_id), 点击"详情"时,访问的是daily/detailGroup接口
}

和原始.pb.go比较可看出, json发生了变化, omitempty没有了,这就达到了自定义标签的效果

相关文章:

通过protoc工具生成proto的pb.go文件以及使用protoc-go-inject-tag工具注入自定义标签

1.ProtoBuf认识,安装以及用法 参考:[golang 微服务] 3. ProtoBuf认识,安装以及golang 中ProtoBuf使用 2. 使用protoc-go-inject-tag工具注入自定义标签 这里有一个案例: syntaxproto3; package test;option go_package ".;test";message MyMessage {int6…...

C语言练习(29)

13个人围成一圈&#xff0c;从第1个人开始顺序报号1、2、3。凡报到“3”者退出圈子&#xff0c;找出最后留在圈子中的人原来的序号。本题要求用链表实现。 #include <stdio.h> #include <stdlib.h>// 定义链表节点结构体 typedef struct Node {int num;struct Nod…...

Android实训九 数据存储和访问

实训9 数据存储和访问 一、【实训目的】 1、 SharedPreferences存储数据; 2、 借助Java的I/O体系实现文件的存储&#xff0c; 3、使用Android内置的轻量级数据库SQLite存储数据; 二、【实训内容】 1、实现下图所示的界面&#xff0c;实现以下功能&#xff1a; 1&#xff…...

实验一---典型环节及其阶跃响应---自动控制原理实验课

一 实验目的 1.掌握典型环节阶跃响应分析的基本原理和一般方法。 2. 掌握MATLAB编程分析阶跃响应方法。 二 实验仪器 1. 计算机 2. MATLAB软件 三 实验内容及步骤 利用MATLAB中Simulink模块构建下述典型一阶系统的模拟电路并测量其在阶跃响应。 1.比例环节的模拟电路 提…...

SOME/IP--协议英文原文讲解2

前言 SOME/IP协议越来越多的用于汽车电子行业中&#xff0c;关于协议详细完全的中文资料却没有&#xff0c;所以我将结合工作经验并对照英文原版协议做一系列的文章。基本分三大块&#xff1a; 1. SOME/IP协议讲解 2. SOME/IP-SD协议讲解 3. python/C举例调试讲解 4.1 Speci…...

matlab中,fill命令用法

在 MATLAB 中&#xff0c;fill 命令用于创建填充多边形的图形对象。使用 fill 可以在二维坐标系中绘制填充的区域&#xff0c;通常用于绘制图形的背景或显示数据分布。 基本语法 fill(X, Y, C)X 和 Y 是同样长度的向量&#xff0c;定义了多边形的顶点坐标。C 是颜色&#xff0…...

【Linux】Linux C判断两个IPv6地址是否有包含关系

功能说明 要判断两个 IPv6 地址是否具有包含关系&#xff0c;包括前缀的比较&#xff0c;可以通过以下步骤实现&#xff1a; 解析 IPv6 地址和前缀&#xff1a;将两个 IPv6 地址和它们的前缀长度解析为二进制形式。生成掩码&#xff1a;根据前缀长度生成掩码。按位比较&#…...

【玩转全栈】----Django基本配置和介绍

目录 Django基本介绍&#xff1a; Django基本配置&#xff1a; 安装Django 创建项目 创建app 注册app Django配置路由URL Django创建视图 启动项目 Django基本介绍&#xff1a; Django是一个开源的、基于Python的高级Web框架&#xff0c;旨在以快速、简洁的方式构建高质量的Web…...

mysql 学习6 DML语句,对数据库中的表进行 增 删 改 操作

添加数据 我们对 testdatabase 数据中 的 qqemp 这张表进行 增加数据&#xff0c;在这张表 下 打开 命令行 query console 在 软件中就是打开命令行的意思 可以先执行 desc qqemp; 查看一下当前表的结构。 插入一条数据 到qqemp 表&#xff0c;插入时要每个字段都有值 insert…...

自动化运维在云环境中的完整实践指南

随着云计算的普及,越来越多的企业将业务迁移到云上。云环境的高动态性和复杂性使得传统的手动运维方式难以应对,自动化运维成为提升效率、降低成本、保障系统稳定性的关键。本文将详细介绍如何在云环境中实施自动化运维,涵盖工具选择、实施步骤和最佳实践。 © ivwdcwso…...

一分钟搭建promehteus+grafana+alertmanager监控平台

为什么要自己搭建一个监控平台 平时进行后端开发&#xff0c;特别是微服务的后端可开发&#xff0c;一定少不了对接监控平台&#xff0c;但是平时进行一些小功能的测试又没有必要每次都手动安装那么多软件进行一个小功能的测试&#xff0c;这里我使用docker-compose搭建了一个…...

【10.2】队列-设计循环队列

一、题目 设计你的循环队列实现。 循环队列是一种线性数据结构&#xff0c;其操作表现基于 FIFO&#xff08;先进先出&#xff09;原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。 循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普…...

设置jmeter界面图标字体大小

设置jmeter界面图标字体大小 方法&#xff1a;点击“选项” -> 点击放大、缩小。&#xff08;可进行全局的菜单、左侧目录结构树、元件界面显示等字体图标的放大、缩小。&#xff09;...

Xposed-Hook

配置 Xposed 模块的 AndroidManifest.xml&#xff1a; <?xml version"1.0" encoding"utf-8"?> <manifest xmlns:android"http://schemas.android.com/apk/res/android"package"your.package.name"><applicationandr…...

设计模式Python版 原型模式

文章目录 前言一、原型模式二、原型模式示例三、原型管理器 前言 GOF设计模式分三大类&#xff1a; 创建型模式&#xff1a;关注对象的创建过程&#xff0c;包括单例模式、简单工厂模式、工厂方法模式、抽象工厂模式、原型模式和建造者模式。结构型模式&#xff1a;关注类和对…...

QT:图像上绘制图形

需求描述 1、展示一张图像 2、在图像上可以使用数据绘制图像&#xff1a;矩形、不规则图形、线条 3、有按键可以选择 概要设计 规划布局如下 1、左边是Qlabel 用于展示图片 2、右边是三个按钮 具体实现 1、 首先设计 UI 界面&#xff0c;对控件进行布局 在 mainwindow.u…...

GPU上没程序在跑但是显存被占用

原因&#xff1a;存在僵尸线程&#xff0c;运行完但是没有释放内存 查看僵尸线程 fuser -v /dev/nvidia*关闭僵尸线程 pkill -9 -u 用户名 程序名 举例&#xff1a;pkill -9 -u grs python参考&#xff1a;https://blog.csdn.net/qq_40206371/article/details/143798866...

wordpress代码结构解析

WordPress 是一个基于 PHP 和 MySQL 的开源内容管理系统&#xff08;CMS&#xff09;&#xff0c;广泛用于构建网站和博客。要解析 WordPress 代码&#xff0c;首先需要了解其核心结构、主要文件和常用的函数。以下是 WordPress 代码解析的基本指南&#xff1a; --- ### 1. *…...

【Unity3D】实现2D小地图效果

目录 一、玩家脚本Player 二、Canvas组件设置 三、小地图相关 四、GameLogicMap脚本修改 基于&#xff1a;【Unity3D】Tilemap俯视角像素游戏案例-CSDN博客 2D玩家添加Dotween移动DOPath效果&#xff0c;移动完成后进行刷新小地图&#xff08;小地图会顺便刷新大地图&…...

关联传播和 Python 和 Scikit-learn 实现

文章目录 一、说明二、什么是 Affinity Propagation。2.1 先说Affinity 传播的工作原理2.2 更多细节2.3 传播两种类型的消息2.4 计算责任和可用性的分数2.4.1 责任2.4.2 可用性分解2.4.3 更新分数&#xff1a;集群是如何形成的2.4.4 估计集群本身的数量。 三、亲和力传播的一些…...

Linux链表操作全解析

Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表&#xff1f;1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql

智慧工地管理云平台系统&#xff0c;智慧工地全套源码&#xff0c;java版智慧工地源码&#xff0c;支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求&#xff0c;提供“平台网络终端”的整体解决方案&#xff0c;提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

遍历 Map 类型集合的方法汇总

1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...

Day131 | 灵神 | 回溯算法 | 子集型 子集

Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者写过很多次这道题了&#xff0c;不想写题解了&#xff0c;大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

家政维修平台实战20:权限设计

目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系&#xff0c;主要是分成几个表&#xff0c;用户表我们是记录用户的基础信息&#xff0c;包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题&#xff0c;不同的角色&#xf…...

【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)

要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况&#xff0c;可以通过以下几种方式模拟或触发&#xff1a; 1. 增加CPU负载 运行大量计算密集型任务&#xff0c;例如&#xff1a; 使用多线程循环执行复杂计算&#xff08;如数学运算、加密解密等&#xff09;。运行图…...

有限自动机到正规文法转换器v1.0

1 项目简介 这是一个功能强大的有限自动机&#xff08;Finite Automaton, FA&#xff09;到正规文法&#xff08;Regular Grammar&#xff09;转换器&#xff0c;它配备了一个直观且完整的图形用户界面&#xff0c;使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...

面向无人机海岸带生态系统监测的语义分割基准数据集

描述&#xff1a;海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而&#xff0c;目前该领域仍面临一个挑战&#xff0c;即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...

rknn toolkit2搭建和推理

安装Miniconda Miniconda - Anaconda Miniconda 选择一个 新的 版本 &#xff0c;不用和RKNN的python版本保持一致 使用 ./xxx.sh进行安装 下面配置一下载源 # 清华大学源&#xff08;最常用&#xff09; conda config --add channels https://mirrors.tuna.tsinghua.edu.cn…...

数据结构第5章:树和二叉树完全指南(自整理详细图文笔记)

名人说&#xff1a;莫道桑榆晚&#xff0c;为霞尚满天。——刘禹锡&#xff08;刘梦得&#xff0c;诗豪&#xff09; 原创笔记&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 上一篇&#xff1a;《数据结构第4章 数组和广义表》…...