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

go binary包

binary包使用与详解

最近在看一个第三方包的库源码,bigcache,发现其中用到了binary 里面的函数,所以准备研究一下。
可以看到binary 包位于encoding/binary,也就是表示这个包的作用是编辑码作用的,看到文档给出的解释是
用于数字和字节序的转换以及变长值的编解码。

Uvarint

从buf解码一个uint64,返回该数字和读取的字节长度,如果发生了错误,该数字为0而读取长度n返回值的意思是:

n == 0 buf 太小了,没读到
n < 0 值太大了,64 bit 装不下,-n 为可以读到的字节数

看以下这个函数,我们不论这个函数是干啥的,我们只用关注

blockSize, n := binary.Uvarint(q.array[index:])
return q.array[index+n : index+int(blockSize)], int(blockSize), nil
从array 中index 的位置之后解析一个unit64, blockSize 为这个值,n 表示读到的字节数
什么意思呢?
比方说我设置了一个package 的一个大小,500byte,我把这个500这个数字编码到byte buf中,这个时候我们通过binary.Uvarint 这个解码出来的有两个值,按照这个方法,blockSize 这个就是500,n 表示编码这个500 占的字节数
那么通过这个peek 方法,实际上我们返回的值就是,从array这个byte buf中取从index+这个编码 之后到packeage的大小字符。说白了就是packege的数据。

// peek returns the data from index and the number of bytes to encode the length of the data in uvarint format
func (q *BytesQueue) peek(index int) ([]byte, int, error) {err := q.peekCheckErr(index)if err != nil {return nil, 0, err}blockSize, n := binary.Uvarint(q.array[index:])return q.array[index+n : index+int(blockSize)], int(blockSize), nil
}

PutUvarint

同样的,我们看下面的函数,我们不用考虑这个函数具体作用,只用分析

headerEntrySize := binary.PutUvarint(q.headerBuffer, uint64(len))
PutUvarint 编码,将什么编码呢,将这个uint64的长度这个数字进行编码,最终放在了q.headerBuffer这个[]byte中,返回的headerEntrySize 这值是什么呢,这个值就是编码用了多少字节。

func (q *BytesQueue) push(data []byte, len int) {headerEntrySize := binary.PutUvarint(q.headerBuffer, uint64(len))q.copy(q.headerBuffer, headerEntrySize)q.copy(data, len-headerEntrySize)if q.tail > q.head {q.rightMargin = q.tail}if q.tail == q.head {q.full = true}q.count++
}

PutUint64

同样的,我们不去管这个函数做了什么(实际上也很好理解),我们具体看

binary.LittleEndian.PutUint64(blob, timestamp)
binary.LittleEndian.PutUint64(blob[timestampSizeInBytes:], hash)
binary.LittleEndian.PutUint16(blob[timestampSizeInBytes+hashSizeInBytes:], uint16(keyLength))
事实上这个就是把timestamp hash keyLength的长度,这三个数字,给他放到blob 这个[]byte中,很明显这三个占了18字节

func wrapEntry(timestamp uint64, hash uint64, key string, entry []byte, buffer *[]byte) []byte {keyLength := len(key)blobLength := len(entry) + headersSizeInBytes + keyLengthif blobLength > len(*buffer) {*buffer = make([]byte, blobLength)}blob := *bufferbinary.LittleEndian.PutUint64(blob, timestamp)binary.LittleEndian.PutUint64(blob[timestampSizeInBytes:], hash)binary.LittleEndian.PutUint16(blob[timestampSizeInBytes+hashSizeInBytes:], uint16(keyLength))copy(blob[headersSizeInBytes:], key)copy(blob[headersSizeInBytes+keyLength:], entry)return blob[:blobLength]
}

Uint64

同样的,我们选择其中一个readEntry 的函数看看,是如何解码的,很简单

length := binary.LittleEndian.Uint16(data[timestampSizeInBytes+hashSizeInBytes:])
length就是我们前面设置的key 的长度

func readEntry(data []byte) []byte {length := binary.LittleEndian.Uint16(data[timestampSizeInBytes+hashSizeInBytes:])// copy on readdst := make([]byte, len(data)-int(headersSizeInBytes+length))copy(dst, data[headersSizeInBytes+length:])return dst
}

封装一个[]byte

考虑一下,我们的网络通信过程中,假设我们需要进行封包的操作。
在这里插入图片描述
假设我么利用上述的方法,对自己的协议进行自定义。
我们看看应用如何实现

func TestCmd(t *testing.T) {b := "hello"bb := []byte(b)encodeB := encode(ICmd{id: 1,cmd: 2,pLen: 5,message: bb})fmt.Println(string(encodeB))icmd := decode(encodeB)fmt.Println(icmd.id)fmt.Println(icmd.cmd)fmt.Println(icmd.pLen)fmt.Println(string(icmd.message))
}
type ICmd struct {id uint32cmd uint32pLen uint32message []byte
}
//然后我们在进行encode 和 decode 操作
const (idFixSize = 4cmdFixSize = 4pLenFixSize = 4SumIdCmdPLenSize = idFixSize+cmdFixSize+pLenFixSize
)
func encode(icmd ICmd) []byte {newBuf := make([]byte,len(icmd.message)+SumIdCmdPLenSize)binary.LittleEndian.PutUint32(newBuf,icmd.id)binary.LittleEndian.PutUint32(newBuf[cmdFixSize:],icmd.cmd)binary.LittleEndian.PutUint32(newBuf[idFixSize+cmdFixSize:],icmd.pLen)copy(newBuf[SumIdCmdPLenSize:],icmd.message)return newBuf
}func decode(data []byte) ICmd{icmd := ICmd{}icmd.id = binary.LittleEndian.Uint32(data[:idFixSize])icmd.cmd = binary.LittleEndian.Uint32(data[idFixSize:idFixSize+cmdFixSize])icmd.pLen = binary.LittleEndian.Uint32(data[idFixSize+cmdFixSize:SumIdCmdPLenSize])icmd.message = data[SumIdCmdPLenSize:]return icmd
}

在这里插入图片描述

相关文章:

go binary包

binary包使用与详解 最近在看一个第三方包的库源码&#xff0c;bigcache&#xff0c;发现其中用到了binary 里面的函数&#xff0c;所以准备研究一下。 可以看到binary 包位于encoding/binary&#xff0c;也就是表示这个包的作用是编辑码作用的&#xff0c;看到文档给出的解释…...

CompletableFuture使用详解(IT枫斗者)

CompletableFuture使用详解 简介 概述 CompletableFuture是对Future的扩展和增强。CompletableFuture实现了Future接口&#xff0c;并在此基础上进行了丰富的扩展&#xff0c;完美弥补了Future的局限性&#xff0c;同时CompletableFuture实现了对任务编排的能力。借助这项能力…...

4.15--设计模式之创建型之责任链模式(总复习版本)---脚踏实地,一步一个脚印

一、什么是责任链模式&#xff1a; 责任链模式属于行为型模式&#xff0c;是为请求创建了一个接收者对象的链&#xff0c;将链中每一个节点看作是一个对象&#xff0c;每个节点处理的请求均不同&#xff0c;且内部自动维护一个下一节点对象。 当一个请求从链式的首端发出时&a…...

STM32+W5500实现以太网通信

STM32系列32位微控制器基于Arm Cortex-M处理器&#xff0c;旨在为MCU用户提供新的开发自由度。它包括一系列产品&#xff0c;集高性能、实时功能、数字信号处理、低功耗/低电压操作、连接性等特性于一身&#xff0c;同时还保持了集成度高和易于开发的特点。本例采用STM32作为MC…...

全网最详细,Jmeter性能测试-性能基础详解,终成测试卷王(一)

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 发起请求 发起HTTP…...

人工智能概述

一、人工智能发展必备三要素 算法 数据 算力 CPU、GPU、TPU 计算力之CPU、GPU对比&#xff1a; CPU主要适合I\O密集型任务GPU主要适合计算密集型任务 什么样的程序适合在GPU上运行&#xff1f; 计算密集型的程序 所谓计算密集型(Compute-intensive)的程序&#xff0c;就是…...

API接口安全—webservice、Swagger、WEBpack

API接口安全—webservice、Swagger、WEBpack1. API接口介绍1.1. 常用的API接口类1.1.1. API接口分类1.1.1.1. 类库型API1.1.1.2. 操作系统型API1.1.1.3. 远程应用型API1.1.1.4. WEB应用型API1.1.1.5. 总结1.1.2. API接口类型1.1.2.1. HTTP类接口1.1.2.2. RPC类接口1.1.2.3. web…...

从前M个字母中取N个的无重复排列 [2*+]

目录 从前M个字母中取N个的无重复排列 [2*+] 程序设计 程序分析 从前M个字母中取N个的无重复排列 [2*+] 输出从前M个字母中取N个的无重复字母排列 Input 输入M N 1<=M=10, N<=M Output 按字典序输出排列 Sample Input 4 2 Sample Output A B A C A D B A B C B …...

ES forceMerge 强制段合并为什么会提升检索性能?

根据以前的测试&#xff0c;forceMerge段合并&#xff0c;将段的个数合并成一个。带来了将近一倍的性能提升&#xff0c;测试过程文档&#xff08;请参考我的另外一篇文章&#xff09;&#xff1a;ES优化实战- forceMerge搜索提升测试报告_es forcemerge_水的精神的博客-CSDN博…...

macOS Ventura 13.3.1 (22E261) Boot ISO 原版可引导镜像

本站下载的 macOS 软件包&#xff0c;既可以拖拽到 Applications&#xff08;应用程序&#xff09;下直接安装&#xff0c;也可以制作启动 U 盘安装&#xff0c;或者在虚拟机中启动安装。另外也支持在 Windows 和 Linux 中创建可引导介质。 macOS Ventura 13.3.1 为 Mac 提供下…...

html+css+JavaScript+json+servlet的社区系统(手把手教学)

目录 课前导读&#xff1a; 一、系统前期准备 二、前端代码的编写 三、登陆页面简介 四、注册页面 五、社区列表页 六、社区详情页 七、社区发帖页 八、注销 九、访问链接 登陆页面http://175.178.20.77:8080/java106_blog_system/login.html 总结&#xff1a; 课前…...

UI Toolkit(1)

UI ToolkitUI Toolkit界面画布设置背景制作UI布局UI Toolkit界面 在Unity 2021LTS版本之后UI Toolkit也被内置在Unity中&#xff0c;Unity有意的想让UI Toolkit 成为UI的主要搭建方式&#xff0c;当然与UGUI相比还是有一定的差别。他们各有有点&#xff0c;这次我们就开始介绍…...

vLive带你走进虚拟直播世界

虚拟直播是什么&#xff1f; 虚拟直播是基于5G实时渲染技术&#xff0c;在绿幕环境下拍摄画面&#xff0c;通过实时抠像、渲染与合成&#xff0c;再推流到直播平台的一种直播技术。尽管这种技术早已被影视工业所采用&#xff0c;但在全民化进程中却是困难重重&#xff0c;面临…...

初谈 ChatGPT

引子 最近&#xff0c;小编发现互联网中的大 V 突然都在用 ChatGPT 做宣传&#xff1a;“ChatGPT不会淘汰你&#xff0c;能驾驭ChatGPT的人会淘汰你”、“带领一小部分人先驾驭ChatGPT”。 确实&#xff0c;ChatGPT这个新生事物&#xff0c;如今被视为蒸汽机、电脑、iPhone 般的…...

JAVA练习103-螺旋矩阵

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 4月9日练习内容 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、题目-螺…...

RecvByteBufAllocator内存分配计算

虽然了解了整个内存池管理的细节&#xff0c;包括它的内存分配的具体逻辑&#xff0c;但是每次从NioSocketChannel中读取数据时&#xff0c;应该分配多少内存去读呢&#xff1f; 例如&#xff0c;客户端发送的数据为1KB , 应该分配多少内存去读呢&#xff1f; 例如&#xff1a;…...

图数据结构与算法

什么是图数据的结构 图是由顶点和边组成的非线性数据结构。顶点有时也称为节点,边是连接图中任意两个节点的线或弧。更正式地说,图由一组顶点 ( V ) 和一组边 ( E ) 组成。该图由 G(E, V) 表示。 图的组成部分 顶点:顶点是图的基本单位。有时,顶点也称为顶点或节点。每个节…...

科普:c语言与C++的区别

C语言和C语言是两种广泛使用的编程语言&#xff0c;尽管它们非常相似&#xff0c;但它们在某些方面也存在不同之处。本文将详细介绍C语言和C语言的区别。 1. 编程范式 C语言是一种过程式编程语言&#xff0c;它的设计目标是为了编写操作系统和其他系统级编程。C语言是一种面向…...

流量整形(GTS和LR)

Generic Traffic Shaping通用流量整形 通用流量整形(简称GTS)可以对不规则或不符合预定流量特性的流量进行整形,以保证网络上下游之间的带宽匹配,避免拥塞发生。 GTS与CAR一样,都采用了令牌桶技术来控制流量。GTS与CAR的主要区别在于:利用CAR进行报文流量控制时,…...

Java接口详细讲解

目录 Java接口概念 Java接口主要有以下特点 Java接口的具体作用 定义接口 实现接口 接口继承 默认方法 静态方法 Java接口概念 Java编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。 …...

元宇宙地产暴跌,林俊杰亏麻了

文/章鱼哥出品/陀螺财经随着元宇宙的兴起&#xff0c;元宇宙地产曾一度被寄予厚望&#xff0c;成为各大投资者追捧的对象。然而&#xff0c;最近的一次元宇宙地产价值暴跌再次提醒我们&#xff0c;高收益背后可能伴随着高风险。根据元宇宙分析平台WeMeta的数据显示&#xff0c;…...

什么是瀑布流布局?瀑布流式布局的优缺点

瀑布流又称瀑布流式布局&#xff0c;是一种多列等宽不等高的一种页面布局方式。 视觉表现为参差不齐的多栏布局。随着页面滚动条向下滚动&#xff0c;这种布局会不断加载数据并附加至当前的尾部。 是一种多列等宽不等高的一种页面布局方式&#xff0c;用于图片比较复杂&#…...

给您的 MongoDB 定期做个体检:MongoDB 诊断

新钛云服已累计为您分享739篇技术干货接下来的一些列文章会为大家介绍日常工作中常用的 NoSQL 产品 MongoDB。主要涉及到&#xff1a;MongoDB 的安装及基本使用 MongoDB 文档查询 MongoDB 复制集 MongoDB 分片集群的介绍及搭建 MongoDB 安全加密 MongoDB 诊断我们会用…...

【云原生进阶之容器】第五章容器运行时5.8--容器热迁移

《云原生进阶之容器》专题索引: 第一章Docker核心技术1.1节——Docker综述第一章Docker核心技术1.2节——Linux容器LXC第一章Docker核心技术1.3节——命名空间Namespace第一章Docker核心技术1.4节——chroot技术第一章Docker核心技术1.5.1节——cgroup综述...

react框架的简单认识

React框架 众所周知&#xff0c;React与Vue&#xff0c;Angular被前端开发人员称为前端的三大框架。在如今&#xff0c;React和Vue相对于老牌的Angular&#xff0c;它们的表现更为出色&#xff0c;常常被各大公司使用。但其中React的技术难度要稍稍大于Vue&#xff0c;不过为了…...

IDEA的基本使用

IDEA的基本使用IDEA的基本使用1 IDEA概述2 IDEA的下载和安装2.1 下载2.2 安装3 IDEA中层级结构介绍3.1 结构分类3.2 结构介绍project&#xff08;项目、工程&#xff09;module&#xff08;模块&#xff09;package&#xff08;包&#xff09;class&#xff08;类&#xff09;3…...

【MySQL】实验八 触发器与存储过程

文章目录 1. 创建商品价格修改记录表2. 创建触发器,当更改商品价格(price列)时,记录价格3. SQL触发器:插入新员工时,同步更新部门表相应人数4. SQL触发器:删除学生数据5. SQL触发器:创建成绩表插入触发器6. SQL存储过程:查询订单7. SQL存储过程:建立存储过程,查询课程…...

Mockito5.2.0学习

Mockito是mocking框架&#xff0c;它让你用简洁的API做测试。而且Mockito简单易学&#xff0c;它可读性强和验证语法简洁。 Mockito 是一个针对 Java 的单元测试模拟框架&#xff0c;它与 EasyMock 和 jMock 很相似&#xff0c;都是为了简化单元测试过程中测试上下文 ( 或者称之…...

用指针实现内存动态分配

导引&#xff1a;已知&#xff1a;变量在使用前必须被定义且安排好存储空间。且变量有这么一些分类&#xff1a;全局变量、静态局部变量【它们的储存一般是在编译时确定&#xff0c;在程序开始执行前完成。】自动变量【在执行进入变量定义所在的复合语句时为它们分配存储&#…...

DBSCAN聚类算法及Python实现

DBSCAN聚类算法 DBSCAN&#xff08;Density-Based Spatial Clustering of Applications with Noise&#xff09;是一种基于密度的聚类算法&#xff0c;可以将数据点分成不同的簇&#xff0c;并且能够识别噪声点&#xff08;不属于任何簇的点&#xff09;。 DBSCAN聚类算法的基…...