通过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个人围成一圈,从第1个人开始顺序报号1、2、3。凡报到“3”者退出圈子,找出最后留在圈子中的人原来的序号。本题要求用链表实现。 #include <stdio.h> #include <stdlib.h>// 定义链表节点结构体 typedef struct Node {int num;struct Nod…...
Android实训九 数据存储和访问
实训9 数据存储和访问 一、【实训目的】 1、 SharedPreferences存储数据; 2、 借助Java的I/O体系实现文件的存储, 3、使用Android内置的轻量级数据库SQLite存储数据; 二、【实训内容】 1、实现下图所示的界面,实现以下功能: 1ÿ…...
实验一---典型环节及其阶跃响应---自动控制原理实验课
一 实验目的 1.掌握典型环节阶跃响应分析的基本原理和一般方法。 2. 掌握MATLAB编程分析阶跃响应方法。 二 实验仪器 1. 计算机 2. MATLAB软件 三 实验内容及步骤 利用MATLAB中Simulink模块构建下述典型一阶系统的模拟电路并测量其在阶跃响应。 1.比例环节的模拟电路 提…...
SOME/IP--协议英文原文讲解2
前言 SOME/IP协议越来越多的用于汽车电子行业中,关于协议详细完全的中文资料却没有,所以我将结合工作经验并对照英文原版协议做一系列的文章。基本分三大块: 1. SOME/IP协议讲解 2. SOME/IP-SD协议讲解 3. python/C举例调试讲解 4.1 Speci…...
matlab中,fill命令用法
在 MATLAB 中,fill 命令用于创建填充多边形的图形对象。使用 fill 可以在二维坐标系中绘制填充的区域,通常用于绘制图形的背景或显示数据分布。 基本语法 fill(X, Y, C)X 和 Y 是同样长度的向量,定义了多边形的顶点坐标。C 是颜色࿰…...
【Linux】Linux C判断两个IPv6地址是否有包含关系
功能说明 要判断两个 IPv6 地址是否具有包含关系,包括前缀的比较,可以通过以下步骤实现: 解析 IPv6 地址和前缀:将两个 IPv6 地址和它们的前缀长度解析为二进制形式。生成掩码:根据前缀长度生成掩码。按位比较&#…...
【玩转全栈】----Django基本配置和介绍
目录 Django基本介绍: Django基本配置: 安装Django 创建项目 创建app 注册app Django配置路由URL Django创建视图 启动项目 Django基本介绍: Django是一个开源的、基于Python的高级Web框架,旨在以快速、简洁的方式构建高质量的Web…...
mysql 学习6 DML语句,对数据库中的表进行 增 删 改 操作
添加数据 我们对 testdatabase 数据中 的 qqemp 这张表进行 增加数据,在这张表 下 打开 命令行 query console 在 软件中就是打开命令行的意思 可以先执行 desc qqemp; 查看一下当前表的结构。 插入一条数据 到qqemp 表,插入时要每个字段都有值 insert…...
自动化运维在云环境中的完整实践指南
随着云计算的普及,越来越多的企业将业务迁移到云上。云环境的高动态性和复杂性使得传统的手动运维方式难以应对,自动化运维成为提升效率、降低成本、保障系统稳定性的关键。本文将详细介绍如何在云环境中实施自动化运维,涵盖工具选择、实施步骤和最佳实践。 © ivwdcwso…...
一分钟搭建promehteus+grafana+alertmanager监控平台
为什么要自己搭建一个监控平台 平时进行后端开发,特别是微服务的后端可开发,一定少不了对接监控平台,但是平时进行一些小功能的测试又没有必要每次都手动安装那么多软件进行一个小功能的测试,这里我使用docker-compose搭建了一个…...
【10.2】队列-设计循环队列
一、题目 设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。 循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普…...
设置jmeter界面图标字体大小
设置jmeter界面图标字体大小 方法:点击“选项” -> 点击放大、缩小。(可进行全局的菜单、左侧目录结构树、元件界面显示等字体图标的放大、缩小。)...
Xposed-Hook
配置 Xposed 模块的 AndroidManifest.xml: <?xml version"1.0" encoding"utf-8"?> <manifest xmlns:android"http://schemas.android.com/apk/res/android"package"your.package.name"><applicationandr…...
设计模式Python版 原型模式
文章目录 前言一、原型模式二、原型模式示例三、原型管理器 前言 GOF设计模式分三大类: 创建型模式:关注对象的创建过程,包括单例模式、简单工厂模式、工厂方法模式、抽象工厂模式、原型模式和建造者模式。结构型模式:关注类和对…...
QT:图像上绘制图形
需求描述 1、展示一张图像 2、在图像上可以使用数据绘制图像:矩形、不规则图形、线条 3、有按键可以选择 概要设计 规划布局如下 1、左边是Qlabel 用于展示图片 2、右边是三个按钮 具体实现 1、 首先设计 UI 界面,对控件进行布局 在 mainwindow.u…...
GPU上没程序在跑但是显存被占用
原因:存在僵尸线程,运行完但是没有释放内存 查看僵尸线程 fuser -v /dev/nvidia*关闭僵尸线程 pkill -9 -u 用户名 程序名 举例:pkill -9 -u grs python参考:https://blog.csdn.net/qq_40206371/article/details/143798866...
wordpress代码结构解析
WordPress 是一个基于 PHP 和 MySQL 的开源内容管理系统(CMS),广泛用于构建网站和博客。要解析 WordPress 代码,首先需要了解其核心结构、主要文件和常用的函数。以下是 WordPress 代码解析的基本指南: --- ### 1. *…...
【Unity3D】实现2D小地图效果
目录 一、玩家脚本Player 二、Canvas组件设置 三、小地图相关 四、GameLogicMap脚本修改 基于:【Unity3D】Tilemap俯视角像素游戏案例-CSDN博客 2D玩家添加Dotween移动DOPath效果,移动完成后进行刷新小地图(小地图会顺便刷新大地图&…...
关联传播和 Python 和 Scikit-learn 实现
文章目录 一、说明二、什么是 Affinity Propagation。2.1 先说Affinity 传播的工作原理2.2 更多细节2.3 传播两种类型的消息2.4 计算责任和可用性的分数2.4.1 责任2.4.2 可用性分解2.4.3 更新分数:集群是如何形成的2.4.4 估计集群本身的数量。 三、亲和力传播的一些…...
srs linux
下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935,SRS管理页面端口是8080,可…...
微服务商城-商品微服务
数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)
宇树机器人多姿态起立控制强化学习框架论文解析 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一) 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...
Netty从入门到进阶(二)
二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架,用于…...
uniapp 小程序 学习(一)
利用Hbuilder 创建项目 运行到内置浏览器看效果 下载微信小程序 安装到Hbuilder 下载地址 :开发者工具默认安装 设置服务端口号 在Hbuilder中设置微信小程序 配置 找到运行设置,将微信开发者工具放入到Hbuilder中, 打开后出现 如下 bug 解…...
WPF八大法则:告别模态窗口卡顿
⚙️ 核心问题:阻塞式模态窗口的缺陷 原始代码中ShowDialog()会阻塞UI线程,导致后续逻辑无法执行: var result modalWindow.ShowDialog(); // 线程阻塞 ProcessResult(result); // 必须等待窗口关闭根本问题:…...
springboot 日志类切面,接口成功记录日志,失败不记录
springboot 日志类切面,接口成功记录日志,失败不记录 自定义一个注解方法 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/***…...
MFE(微前端) Module Federation:Webpack.config.js文件中每个属性的含义解释
以Module Federation 插件详为例,Webpack.config.js它可能的配置和含义如下: 前言 Module Federation 的Webpack.config.js核心配置包括: name filename(定义应用标识) remotes(引用远程模块࿰…...
华为OD最新机试真题-数组组成的最小数字-OD统一考试(B卷)
题目描述 给定一个整型数组,请从该数组中选择3个元素 组成最小数字并输出 (如果数组长度小于3,则选择数组中所有元素来组成最小数字)。 输入描述 行用半角逗号分割的字符串记录的整型数组,0<数组长度<= 100,0<整数的取值范围<= 10000。 输出描述 由3个元素组成…...
高考志愿填报管理系统---开发介绍
高考志愿填报管理系统是一款专为教育机构、学校和教师设计的学生信息管理和志愿填报辅助平台。系统基于Django框架开发,采用现代化的Web技术,为教育工作者提供高效、安全、便捷的学生管理解决方案。 ## 📋 系统概述 ### 🎯 系统定…...
