一文了解io.ReadAtLeast函数
1. 引言
io.ReadAtLeast 函数是Go标准库提供的一个非常好用的函数,能够指定从数据源最少读取到的字节数。本文我们将从io.ReadAtLeast 函数的基本定义出发,讲述其基本使用和实现原理,以及一些注意事项,基于此完成对io.ReadAtLeast 函数的介绍。
2. 基本说明
2.1 基本定义
io.ReadAtLeast 函数用于从读取器(io.Reader)读取至少指定数量的字节数据到缓冲区中。函数定义如下:
func ReadAtLeast(r Reader, buf []byte, min int) (n int, err error)
其中r 是数据源,从它读取数据,而buf是用于接收读取到的数据的字节切片,min是要读取的最小字节数。io.ReadAtLeast 函数会尝试从读取器中最少读取 min 个字节的数据,并将其存储在 buf 中。
2.2 使用示例
下面是一个示例代码,演示如何使用 io.ReadAtLeast 函数从标准输入读取至少 5 个字节的数据:
package main
import (
"fmt"
"io"
"os"
)
func main() {
buffer := make([]byte, 10)
n, err := io.ReadAtLeast(os.Stdin, buffer, 5)
if err != nil {
fmt.Println("读取过程中发生错误:", err)
return
}
fmt.Printf("成功读取了 %d 个字节:%s\n", n, buffer)
}
在这个例子中,我们创建了一个长度为 10 的字节切片 buffer,并使用 io.ReadAtLeast 函数从标准输入读取至少 5 个字节的数据到 buffer 中。下面是一个可能的输出,具体如下:
hello,world
成功读取了 10 个字节:hello,worl
这里其指定 min 为5,也就是最少读取5个字节的数据,此时调用io.ReadAtLeast函数一次性读取到了10个字节的数据,此时也满足要求。这里也间接说明了io.ReadAtLeast只保证最少要读取min个字节的数据,但是并不限制更多数据的读取。
3. 实现原理
在了解了io.ReadAtLeast 函数的基本定义和使用后,这里我们来对io.ReadAtLeast 函数的实现来进行基本的说明,加深对io.ReadAtLeast 函数的理解。
其实 io.ReadAtLeast 的实现非常简单,其定义一个变量n, 保存了读取到的字节数,然后不断调用数据源Reader中的 Read 方法读取数据,然后自增变量n 的值,直到 n 大于 最小读取字节数为止。下面来看具体代码的实现:
func ReadAtLeast(r Reader, buf []byte, min int) (n int, err error) {
// 传入的缓冲区buf长度 小于 最小读取字节数min的值,此时直接返回错误
if len(buf) < min {
return 0, ErrShortBuffer
}
// 在 n < min 时,不断调用Read方法读取数据
// 最多读取 len(buf) 字节的数据
for n < min && err == nil {
var nn int
nn, err = r.Read(buf[n:])
// 自增 n 的值
n += nn
}
if n >= min {
err = nil
} else if n > 0 && err == EOF {
// 读取到的数据字节数 小于 min值,同时数据已经全部读取完了,此时返回 ErrUnexpectedEOF
err = ErrUnexpectedEOF
}
return
}
4. 注意事项
4.1 注意无限等待情况的出现
从上面io.ReadAtLeast 的实现可以看出来,如果一直没有读取到指定数量的数据,同时也没有发生错误,将一直等待下去,直到读取到至少指定数量的字节数据,或者遇到错误为止。下面举个代码示例来展示下效果:
func main() {
buffer := make([]byte, 5)
n, err := io.ReadAtLeast(os.Stdin, buffer, 5)
if err != nil {
fmt.Println("读取过程中发生错误:", err)
return
}
fmt.Printf("成功读取了 %d 个字节:%s\n", n, buffer)
}
在上面代码的例子中,会调用io.ReadAtLeast 函数从标准输入中读取 5 个字节的数据,如果标准输入一直没有输够5个字节,此时这个函数将会一直等待下去。比如下面的这个输入,首先输入了he两个字符,然后回车,由于还没有达到5个字符,此时io.ReadAtLeast函数一直不会返回,只有再输入llo这几个字符后,才满足5个字符,才能够继续执行,所以在使用io.ReadAtLeast函数时,需要注意无限等待的情况。
he
llo
成功读取了 5 个字节:he
ll
4.2 确保 buf 的大小足够容纳至少 min 个字节的数据
在调用io.ReadAtLeast函数时,需要保证缓冲区buf的大小需要满足min,如果缓冲区的大小比 min 参数还小的话,此时将永远满足不了 最少读取 min个字节数据的要求。
从上面io.ReadAtLeast 的实现可以看出来,如果其发现buf的长度小于 min,其也不会尝试去读取数据,其会直接返回一个ErrShortBuffer 的错误,下面通过一个代码展示下效果:
func main() {
buffer := make([]byte, 3)
n, err := io.ReadAtLeast(os.Stdin, buffer, 5)
if err != nil {
fmt.Println("读取过程中发生错误:", err)
return
}
fmt.Printf("成功读取了 %d 个字节:%s\n", n, buffer)
}
比如上述函数中,指定的buffer的长度为3,但是io.ReadAtLeast要求最少读取5个字节,此时buffer并不能容纳5个字节的数据,此时将会直接ErrShortBuffer错误,如下:
读取过程中发生错误: short buffer
5. 总结
io.ReadAtLeast函数是Go语言标准库提供的一个工具函数,能够从数据源读取至少指定数量的字节数据到缓冲区中。 我们先从 io.ReadAtLeast 函数的基本定义出发,之后通过一个简单的示例,展示如何使用io.ReadAtLeast函数实现至少读取指定字节数据。
接着我们讲述了io.ReadAtLeast函数的实现原理,其实就是不断调用源Reader的Read方法,直接读取到的数据数满足要求。
在注意事项方面,则强调了调用io.ReadAtLeast 可能出现无限等待的问题,以及需要确保 buf 的大小足够容纳至少 min 个字节的数据。
基于此,完成了对io.ReadAtLeast函数的介绍,希望对你有所帮助。
一文了解io.ReadAtLeast函数的更多相关文章
- 使用korofileheader插件vs code添加文件头注释和函数注释
korofileheadervs code添加文件头注释和函数注释1.extensions搜索fileheader,安装koroFileHeader2.设置:edit=>perference=& ...
- openssl之BIO系列之6---BIO的IO操作函数
BIO的IO操作函数 ---依据openssl doc/crypto/bio/bio_read.pod翻译和自己的理解写成 (作者:DragonKing Mail:wzhah ...
- VA中用文件头注释和函数头注释Suggestions
写C++代码,不能不用VA,这里贴两个我最常用的注释Suggestions. [1.File Header 文件头注释] /*** @file $FILE_BASE$.$FILE_EXT$* ...
- 六、文件IO——fcntl 函数 和 ioctl 函数
6.1 fcntl 函数 6.1.1 函数介绍 #include <unistd.h> #include <fcntl.h> int fcntl(int fd, int cmd ...
- 五、文件IO——dup 函数
5.1 dup 函数---复制文件描述符 5.1.1 简单cat实现及输入输出重定向 io.c #include <sys/types.h> #include <sys/stat.h ...
- Linux文件IO操作函数概述
文件概述 Linux中,一切皆文件.文件为操作系统服务和设备提供了一个简单而一致的接口.这意味着程序完全可以像使用文件那样使用磁盘文件.串行口.打印机和其他设备. 也就是说,大多数情况下,你只需要使用 ...
- python文档字符串(函数使用说明)
关键字: 函数说明.help()函数 1.效果图: 2.代码: # 文档字符串( doc str) 是 函数使用说明 # 用法: 在函数第一行写一个字符串 def fn(*nums): ''' 函数的 ...
- js文档视口高度函数
objwin=window;objBody=document.body;objDel=document.documentElement; 关于弹窗时候用到 function getPageHeig ...
- GCC,GDB,Makefile和IO复用函数
2015.1.22 c高级的环境搭建:GCC编译器:全称 GNU CC,是GNU工具(tool chain)的一种,源码编译成机器码,gcc的编译依赖于很多小工具4.3.3和3.4.3版本的比较稳定 ...
- 把excel每一行中的数据输出为一个txt文档的VBA函数
excel vba代码: Sub makeTxt() For i = 1 To 1088'从第1行到1088行(最后一行) On Error Resume Next'出现错误时继续运行脚本 Open ...
随机推荐
- LINUX 下LAMP之yum方法部署环境
一. 系统组成 系统由前台网站和后台保种服务两部分组成,其中后台保种可以扩展成多台设备,提高保种的资源量以及性能.下面安装以houtaiip代表后台保重服务器ip地址,qiantaiip代表前台网站i ...
- Vue修改单页面背景颜色
- TiDB Lightning导入超大型txt文件实践
背景 TiDB 提供了很多种数据迁移的方式,但这些工具/方案普遍对MySQL比较友好,一旦涉及到异构数据迁移,就不得不另寻出路,借助各种开源或商业的数据同步工具.其实数据在不同系统的流转当中,有一种格 ...
- 【深入浅出 Yarn 架构与实现】6-3 NodeManager 分布式缓存
不要跳过这部分知识,对了解 NodeManager 本地目录结构,和熟悉 Container 启动流程有帮助. 一.分布式缓存介绍 主要作用就是将用户应用程序执行时,所需的外部文件资源下载缓存到各个节 ...
- 2023-05-11:给你一个 m x n 的二进制矩阵 grid, 每个格子要么为 0 (空)要么为 1 (被占据), 给你邮票的尺寸为 stampHeight x stampWidth。 我们想将
2023-05-11:给你一个 m x n 的二进制矩阵 grid, 每个格子要么为 0 (空)要么为 1 (被占据), 给你邮票的尺寸为 stampHeight x stampWidth. 我们想将 ...
- 2022-10-09:我们给出了一个(轴对齐的)二维矩形列表 rectangles 。 对于 rectangle[i] = [x1, y1, x2, y2],其中(x1,y1)是矩形 i 左下角的坐
2022-10-09:我们给出了一个(轴对齐的)二维矩形列表 rectangles . 对于 rectangle[i] = [x1, y1, x2, y2],其中(x1,y1)是矩形 i 左下角的坐标 ...
- prefetch_related() 一对多、多对多查询优化,反向查询
prefetch_related() 一对多.多对多查询优化,反向查询 Student.objects.filter(age__lt=30).prefetch_related('course') # ...
- idea构建grpc项目
转载请注明出处: 安装protocbuf插件 idea 建议下载一个 protobuf的插件, 可以有代码提示. 这里直接去pluging里搜就行了. 在idea的plugins中搜索proto,然后 ...
- MAUI Android 关联文件类型
实现效果 打开某个文件,后缀是自己想要的类型,在弹出的窗口(用其它应用打开)的列表中显示自己的应用图标 点击后可以获得文件信息以便于后续的操作 实现步骤 以注册.bin后缀为例,新建一个MAUI项目 ...
- Apache Hudi 1.x 版本重磅功能展望与讨论
Apache Hudi 社区正在对Apache Hudi 1.x版本功能进行讨论,欢迎感兴趣同学参与讨论,PR链接:https://github.com/apache/hudi/pull/8679/f ...