当前位置: 首页 > 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来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。 …...

练习(含atoi的模拟实现,自定义类型等练习)

一、结构体大小的计算及位段 &#xff08;结构体大小计算及位段 详解请看&#xff1a;自定义类型&#xff1a;结构体进阶-CSDN博客&#xff09; 1.在32位系统环境&#xff0c;编译选项为4字节对齐&#xff0c;那么sizeof(A)和sizeof(B)是多少&#xff1f; #pragma pack(4)st…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

使用分级同态加密防御梯度泄漏

抽象 联邦学习 &#xff08;FL&#xff09; 支持跨分布式客户端进行协作模型训练&#xff0c;而无需共享原始数据&#xff0c;这使其成为在互联和自动驾驶汽车 &#xff08;CAV&#xff09; 等领域保护隐私的机器学习的一种很有前途的方法。然而&#xff0c;最近的研究表明&…...

如何在看板中有效管理突发紧急任务

在看板中有效管理突发紧急任务需要&#xff1a;设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP&#xff08;Work-in-Progress&#xff09;弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中&#xff0c;设立专门的紧急任务通道尤为重要&#xff0c;这能…...

【2025年】解决Burpsuite抓不到https包的问题

环境&#xff1a;windows11 burpsuite:2025.5 在抓取https网站时&#xff0c;burpsuite抓取不到https数据包&#xff0c;只显示&#xff1a; 解决该问题只需如下三个步骤&#xff1a; 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...

html-<abbr> 缩写或首字母缩略词

定义与作用 <abbr> 标签用于表示缩写或首字母缩略词&#xff0c;它可以帮助用户更好地理解缩写的含义&#xff0c;尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时&#xff0c;会显示一个提示框。 示例&#x…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!

简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求&#xff0c;并检查收到的响应。它以以下模式之一…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf

FTP 客服管理系统 实现kefu123登录&#xff0c;不允许匿名访问&#xff0c;kefu只能访问/data/kefu目录&#xff0c;不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...

虚拟电厂发展三大趋势:市场化、技术主导、车网互联

市场化&#xff1a;从政策驱动到多元盈利 政策全面赋能 2025年4月&#xff0c;国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》&#xff0c;首次明确虚拟电厂为“独立市场主体”&#xff0c;提出硬性目标&#xff1a;2027年全国调节能力≥2000万千瓦&#xff0…...

Caliper 负载(Workload)详细解析

Caliper 负载(Workload)详细解析 负载(Workload)是 Caliper 性能测试的核心部分,它定义了测试期间要执行的具体合约调用行为和交易模式。下面我将全面深入地讲解负载的各个方面。 一、负载模块基本结构 一个典型的负载模块(如 workload.js)包含以下基本结构: use strict;/…...