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

Go的bytes.Buffer

Go的bytes.Buffer

文章目录

  • Go的bytes.Buffer
    • 一、bytes.Buffer 的基础知识
    • 二、`bytes.Buffer`类型的值,已读计数的作用
    • 三、`bytes.Buffer`的扩容策略
    • 四、`bytes.Buffer`的哪些方法会造成内容的泄露

一、bytes.Buffer 的基础知识

strings.Builder一样,bytes.Buffer也是开箱即用的。

bytes.Buffer类型的用途主要是作为字节序列的缓冲区。

在内部,bytes.Buffer类型使用字节切片作为内容容器,并有一个int类型的字段作为已读计数,这个已读计数无法通过bytes.Buffer提供的方法计算出来。

	var buffer1 bytes.Buffercontents := "Simple byte buffer for marshaling data"// Write contents "Simple byte buffer for marshaling data"fmt.Printf("Write contents %q\n", contents)buffer1.WriteString(contents)// The length of buffer: 38fmt.Printf("The length of buffer: %d\n", buffer1.Len())// The capacity of buffer: 64fmt.Printf("The capacity of buffer: %d\n", buffer1.Cap())

strings.Reader类型的Len方法一样,buffer1的Len方法返回的也是内容容器中未被读取部分的长度,而不是其中已存内容的总长度。

Buffer 值的长度是未读内容的长度,而不是已读内容的长度。

	p1 := make([]byte, 7)n, _ := buffer1.Read(p1)// 7 bytes were read. (call Read)fmt.Printf("%d bytes were read. (call Read)\n", n)// The length of buffer: 31fmt.Printf("The length of buffer: %d\n", buffer1.Len())// The capacity of buffer: 64fmt.Printf("The capacity of buffer: %d\n", buffer1.Cap())

Buffer值的容量是它的内容容器(也就是那个字节切片)的容量,它只与当前值之上的写操作有关,并随着内容的写入而不断增长。

二、bytes.Buffer类型的值,已读计数的作用

  • 读取内容时,相应方法会依据已读计数找到未读内容,并在读取之后更新计数;

    相应方法包括所有名称以Read开头的方法,以及Next方法和WriteTo方法。

  • 写入内容时,如需扩容,相应方法会根据已读计数实现扩容策略;

    写入时,如果没有足够的容量,就会对容器进行扩容。

    扩容时,方法会在必要时,依据已读计数找到未读部分,并把其中的内容拷贝到扩展容器的头部位置。然后,方法会把已读计数值置为0。

    相应方法包括所有名称以Write开头的方法,以及ReadFrom方法。

  • 截断内容时,相应方法截断的时已读计数代表索引之后的未读部分;

    截断方法Truncate,接受一个int类型的参数,表示在截断时需要保留头部多少个字节。

    这里的头部是未读部分的头部,而不是内容容器的头部。

    这种情况下,已读计数的值再加上参数值后得到的和,就是内容容器新的总长度。

  • 读回退时,相应方法会使用已读计数记录回退点;

    用于读回退的方法有UnreadByte和UnreadRune。这两个方法分别用于回退一个字节和回退一个Unicode字符。

    回退的前提是,在调用它们之前的那一个操作必须是“读取”,并且是成功的读取,否则这些方法就只会忽略后续操作并返回一个非nil的错误值。

    只有紧挨在调用ReadRune 方法之后,对UnreadRune方法对调用才能够成功完成。

  • 重置内容时,相应方法会把已读计数置为0;

  • 导出内容时,相应方法只会导出已读计数代表的索引之后的未读部分;

    Buffer值的Bytes和String方法,只会访问未读部分的内容,并返回相应的结果值。

  • 获取长度时,相应方法会依据已读计数和内容容器的长度,计算未读部分的长度并返回;

    Buffer值的Len方法返回的是内容容器未读部分的长度。

三、bytes.Buffer的扩容策略

bytes.Buffer既可以手动扩容,也可以自动扩容。除非完全确定后续内容所需的字节数,否则让Buffer自动扩容就好了。这两种方式的扩容策略一样。

扩容策略:

  1. 判断内容容器的剩余容量,是否满足调用方的要求,是否足够容纳新的内容;

  2. 如果剩余容量满足容纳新的内容,就在当前的内容容器之上,进行长度扩容;

    buf = buf[:length+need]
    
  3. 如果剩余容量不满足容纳新的内容,就会用新的内容容器去替代原有的内容容器,从而实现扩容;

  4. 这里有一个优化,如果当前内容容器的容量的一半,仍然大于或等于现有长度(即未读字节数)再加上另需字节数的和,即:

cap(buf)/2 >= len(buf) + need

那么扩容代码就会复用现有的内容容器,并把容器中的未读内容拷贝到它的头部位置。

这意味着,其中的已读内容,将会全部被未读内容和之后的新内容覆盖掉。

  1. 如果当前内容容器的容量小于新长度的二倍。这时,就会把原有容器中的未读内容拷贝进去,最后再用新的容器替换掉原有的容器。这个新容器将会等于原有容量的二倍,再加上另需字节数的和。

    新容器的容量 = 原有容量 * 2 + 所需字节数
    
  2. 扩容还会把已读计数置为0。

  3. 对于处于零值状态的Buffer值来说,如果第一次扩容时另需的字节数小于等于64,那么该值就会基于一个预先定义好的、长度为64的字节数组来创建内容容器。

    这种情况下,容器的容量就是64。这样做的目的是为了让Buffer值在刚被真正使用的时候,可以快速的做好准备。

四、bytes.Buffer的哪些方法会造成内容的泄露

这里的内容泄露是指,使用Buffer值的一方通过某种非标准的方式,得到本不该得到的内容。

bytes.Buffer中,Bytes方法和Next方法都有可能会造成内容的泄露。原因在于,它们都把基于内容容器的切片直接返回给了方法的调用方。

通过切片,我们可以直接访问和操纵它们的底层数组,不论这个切片是基于某个数组得来的,还是痛哦过对另一个切片做切片操作获得的,都是如此。

bytes.Buffer的Bytes方法和Next方法返回的字节切片,都是通过对内容容器的切片做切片操作得到的。

	contents := "ab"buffer1 := bytes.NewBufferString(contents)// The capacity of new buffer with contents "ab": 8// 容量为何为8,看 runtime/string.go#stringtoslicebyte()fmt.Printf("The capacity of new buffer with contents %q: %d\n", contents, buffer1.Cap())unreadBytes := buffer1.Bytes()// The unread bytes of the buffer: [97 98]fmt.Printf("The unread bytes of the buffer: %v\n", unreadBytes)buffer1.WriteString("cdefg")// The capacity of new buffer with contents "ab": 8fmt.Printf("The capacity of new buffer with contents %q: %d\n", contents, buffer1.Cap())unreadBytes = unreadBytes[:cap(unreadBytes)]// 基于前面的内容获取到结果值// The unread bytes of the buffer: [97 98 99 100 101 102 103 0]fmt.Printf("The unread bytes of the buffer: %v\n", unreadBytes)// 操纵bufferunreadBytes[len(unreadBytes)-2] = byte('X')// The unread bytes of the buffer: [97 98 99 100 101 102 88 0]fmt.Printf("The unread bytes of the buffer: %v\n", unreadBytes)

相关文章:

Go的bytes.Buffer

Go的bytes.Buffer 文章目录Go的bytes.Buffer一、bytes.Buffer 的基础知识二、bytes.Buffer类型的值,已读计数的作用三、bytes.Buffer的扩容策略四、bytes.Buffer的哪些方法会造成内容的泄露一、bytes.Buffer 的基础知识 与strings.Builder一样,bytes.Bu…...

k8s学习之路 | Day19 k8s 工作负载 Deployment(上)

文章目录1. Deployment 基础1.1 什么是 Deployment1.2 简单体验 Deployment1.3 Deployment 信息描述1.4 如何编写 Deployment2. Deployment 简单特性2.1 赋予 Pod 故障转移和自愈能力2.2 更新 Deployment2.3 回滚 Deployment2.4 暂停、恢复 Deployment 的上线过程2.5 Deploymen…...

php宝塔搭建部署实战六零导航页LyLme_Spage源码

大家好啊,我是测评君,欢迎来到web测评。 本期给大家带来一套php开发的六零导航页LyLme_Spage源码。感兴趣的朋友可以自行下载学习。 技术架构 PHP7.0 nginx mysql5.7 JS CSS HTMLcnetos7以上 宝塔面板 文字搭建教程 下载源码,宝塔添…...

SpringBoot (三) 整合数据库访问 jdbcTemplate、MyBatis

哈喽,大家好,我是有勇气的牛排(全网同名)🐮🐮🐮 有问题的小伙伴欢迎在文末评论,点赞、收藏是对我最大的支持!!!。 Spring Data了解下&#xff1…...

机器学习、数据挖掘和统计模式识别学习(Matlab代码实现)

目录 💥1 概述 📚2 运行结果 🎉3 参考文献 👨‍💻4 Matlab代码 💥1 概述 机器学习是让计算机在没有明确编程的情况下采取行动的科学。在过去的十年中,机器学习为我们提供了自动驾驶汽车&…...

Java修饰符-ai生成

Java修饰符 Java的修饰符有哪几种 Java的修饰符有以下几种: 访问修饰符:public、protected、private和默认访问修饰符。 非访问修饰符:final、abstract、static、synchronized、volatile、transient、native、strictfp和Deprecated。 什么…...

kafka部署安装

kafka介绍 kafka是一个分布式的消息队列系统,适合离线和在线消费,扩展性好 kafka部署 安装包获取: 链接:https://pan.baidu.com/s/1y32yvZU-CAHBtbEfnHkJzQ 提取码:y9vb –来自百度网盘超级会员V5的分享 安装目录为…...

使用asio实现一个单线程异步的socket服务程序

文章目录前言代码前言 之前,我使用epoll实现过一个C的后端服务程序,见:从头开始实现一个留言板-README_c做一个留言板_大1234草的博客-CSDN博客 但是它不够简便,无法轻松的合并到其他代码中。并且,由于程序中使用epo…...

大型JAVA版云HIS医院管理系统源码 Saas应用+前后端分离+B/S架构

SaaS运维平台多集团多医院入驻强大的电子病历完整文档 有源码,有演示! 云HIS系统技术栈: 1、前端框架:AngularNginx 2、后台框架:JavaSpring,SpringBoot,SpringMVC,SpringSecurity&…...

1 网关介绍

网关介绍 在微服务架构中,一个系统会被拆分为很多个微服务。那么作为客户端要如何去调用这么多的微服务呢?如果没有网关的存在,我们只能在客户端记录每个微服务的地址,然后分别去调用。这样的话会产生很多问题,例如&a…...

Java中Scanner用法

Java中Scanner用法 Scanner可以实现程序和人的交互,用户可以利用键盘进行输入。 不同类型的输入: String ssc.next(); //接受字符串数据 System.out.println(s);int s1 sc.nextInt();//接受整型数据 System.out.println(s1);double s2 sc.nextDouble…...

malloc实现原理探究

2021年末面试蔚来汽车,面试官考察了malloc/free的实现机制。当时看过相关的文章,有一点印象,稍微说了一点东西,不过自己感到不满意。今天尝试研究malloc的实现细节,看了几篇博文,发现众说纷纭,且…...

Spring——整合junit4、junit5使用方法

spring需要创建spring容器&#xff0c;每次创建容器单元测试是测试单元代码junit4依赖<?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-i…...

计算机网络的一些思考(待完善)

文章目录概念1. 缓存2. 备份&#xff08;副本&#xff09;3. 硬件和软件&#xff1a;4.端口5. 二进制协议vs文本协议6. 虚拟7.分布式8.广播域和冲突域的区别9本地地址协议1.CSMA/CD协议2.IP协议3.路由算法协议&#xff08;RIP&#xff0c;OSPF&#xff0c;BGP&#xff09;4.ARP…...

【第一章】谭浩强C语言课后习题答案

1.什么是程序?什么是程序设计? 程序:就是一组能识别和执行的指令,每一条指令使计算机执行特定的操作 程序设计:是指从确定任务到得到结果、写出文档的全过程 2.为什么需要计算机语言?高级语言有哪些特点? 为什么需要计算机语言:计算机语言解决了人和计算机交流是的…...

最新版本vue3+vite重构尚品汇(解决接口问题)第21-50集

第21集&#xff0c;第22集&#xff1a;照敲就行&#xff0c;引入概念。 第23集&#xff1a;防抖概念&#xff1a;前面所有的触发被取消&#xff0c;最后一次执行在规定的时间之后才会触发&#xff0c;只会执行一次。Lodash插件里面封装了函数的防抖和节流的业务。用到lodash确实…...

【超级猜图案例上半部分的实现 Objective-C语言】

一、超级猜图这么一个案例: 1.实现之后的效果是这样的: 1)中间有一个图片,点一下,能放大,背景变半透明的黑色: 2)再点一下图片,或者点周围黑色的阴影,图片回归原状, 3)右边有一个“大图”按钮,点一下,实现跟点图片一样的效果, 4)左边有一个“提示”按钮,点…...

刷题笔记4 | 24. 两两交换链表中的节点、19. 删除链表的倒数第N个节点、面试题 02.07. 链表相交、142.环形链表II

24. 两两交换链表中的节点 给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff08;即&#xff0c;只能进行节点交换&#xff09;。 输入&#xff1a;head [1,2,3,4] 输出&#xff1a…...

15、正则表达式

目录 一、元字符 二、限定修饰符 一、元字符 正则表达式通常被用于判断语句中&#xff0c;用来检查某一字符串是否满足某一格式。正则表达式是含有一些具有特殊意义字符的字符串&#xff0c;这些特殊字符称为正则表达式的元字符。例如&#xff0c;“\\d”表示数字0~9中的任何…...

javaWeb核心01-HTTPTomcatServlet

文章目录HTTP&Tomcat&Servlet1&#xff0c;Web概述1.1 Web和JavaWeb的概念1.2 JavaWeb技术栈1.2.1 B/S架构1.2.2 静态资源1.2.3 动态资源1.2.4 数据库1.2.5 HTTP协议1.2.6 Web服务器1.3 Web核心课程安排2, HTTP2.1 简介2.2 请求数据格式2.2.1 格式介绍2.2.2 实例演示2.…...

深圳大学计软《面向对象的程序设计》实验16 期末复习

A. 一、会员积分&#xff08;期末模拟&#xff09; 题目描述 某电商网站的会员分为&#xff1a;普通、贵宾两个级别 普通会员类Member&#xff0c;包含编号、姓名、积分三个属性&#xff0c;编号和积分是整数&#xff0c;姓名是字符串 操作包括构造、打印、积分累加、积分兑…...

Linux基础命令(一)

文章目录1、时间命令&#xff1a;date2、日历命令&#xff1a;cal3、计算器程序&#xff1a;bc4、基础组合键5、正确的关机指令使用5.1 将数据同步写入硬盘中的指令&#xff1a; sync5.2 惯用的关机指令&#xff1a; shutdown5.3 重新开机&#xff0c;关机&#xff1a; reboot,…...

RocketMQ Broker消息处理流程剩余源码解析

&#x1f34a; Java学习&#xff1a;Java从入门到精通总结 &#x1f34a; 深入浅出RocketMQ设计思想&#xff1a;深入浅出RocketMQ设计思想 &#x1f34a; 绝对不一样的职场干货&#xff1a;大厂最佳实践经验指南 &#x1f4c6; 最近更新&#xff1a;2023年3月4日 &#x1…...

JQuery入门基础

目录 1.初识 下载 使用 JQuery&#xff08;核心&#xff09;对象 2.选择器 基础选择器 层次选择器 后代选择器 子代选择器 兄弟选择器 相邻选择器 3.JQuery DOM操作 创建元素 插入元素 删除元素 遍历元素 属性操作 获取属性 设置属性 删除属性 样式操作 …...

kafka 构建双向SSL认证

kafka 安装 以下内容均已完成测试&#xff0c;按照教程搭建你会得到一个双向ssl认证的kafka broker&#xff0c;并能通过ip以及域名访问&#xff0c;笔者能力有限如果文章内容存在问题烦请各位指出。 搭建单机Kafka 需求 centos 7kafka_2.12-2.6.0jdk8&#xff08;文档中统…...

推荐一个.Net Core开发的Websocket群聊、私聊的开源项目

更多开源项目请查看&#xff1a;一个专注推荐.Net开源项目的榜单 今天给大家推荐一个使用Websocket协议实现的、高性能即时聊天组件&#xff0c;可用于群聊、好友聊天、游戏直播等场景。 项目简介 这是一个基于.Net Core开发的、简单、高性能的通讯组件&#xff0c;支持点对点…...

华为OD机试Golang解题 - 事件推送 | 含思路

华为Od必看系列 华为OD机试 全流程解析+经验分享,题型分享,防作弊指南)华为od机试,独家整理 已参加机试人员的实战技巧华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典文章目录 华为Od必看系列使用说明本期题目…...

将微信小程序页面转为图片

最近做项目遇到一个需求,那就是要将某个页面转为图片然后传给后端,我仔细找了一圈,发现官方那个Api也就是wx.canvasToTempFilePath生成的图片很有可能为空,太坑了,于是我放弃用它了,选择了用wxml2canvas。 安装wxml2canvas npm init npm install wxml2canvas --save --…...

LINE、SDNE和struc2vec图嵌入算法学习笔记

引言 在cs224w课程中&#xff0c;我先后总结了deepwalk、node2vec&#xff0c;这两种算是最经典也是最主流的做法&#xff0c;而在 图节点嵌入相关算法学习笔记 中&#xff0c;从头至尾&#xff0c;将一些经典算法用wiki的数据集复现了一下&#xff0c;所以本篇博文&#xff0…...

Buuctf Younger-drive 题解

目录 一.查壳 二.运行缺少dll 三.主函数 四.hObject线程 五.Thread线程 六.judge函数 七.解题脚本 这题的关键在于了解一定的线程相关知识 一.查壳 32位带壳,用upx脱壳 二.运行缺少dll 后续尝试了各种方法修复dll但是还是运行不了 值得一提的是脱壳后的程序不能动态调试…...