一文了解io.ReadAtLeast函数

这篇具有很好参考价值的文章主要介绍了一文了解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函数的介绍,希望对你有所帮助。文章来源地址https://www.toymoban.com/news/detail-557827.html

到了这里,关于一文了解io.ReadAtLeast函数的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 一文了解Go语言的函数

    函数是编程中不可或缺的组成部分,无论是在 Go 语言还是其他编程语言中,函数都扮演着重要的角色。函数能够将一系列的操作封装在一起,使得代码更加模块化、可重用和易于维护。 在本文中,我们将详细介绍Go语言中函数的概念和使用方法,包括函数的定义、参数和返回

    2024年02月09日
    浏览(36)
  • 一文了解函数设计的最佳实践

    良好设计的函数具有清晰的职责和逻辑结构,提供准确的命名和适当的参数控制。它们促进代码复用、支持团队协作,降低维护成本,并提供可测试的代码基础。通过遵循最佳实践,我们能够编写出高质量、可读性强的代码,从而提高开发效率和软件质量。下面我们将一一描

    2024年02月10日
    浏览(23)
  • 一文了解Go语言的匿名函数

    无论是在 Go 语言还是其他编程语言中,匿名函数都扮演着重要的角色。在本文中,我们将详细介绍 Go 语言中匿名函数的概念和使用方法,同时也提供一些考虑因素,从而帮助在匿名函数和命名函数间做出选择。 匿名函数是一种没有函数名的函数。它是在代码中直接定义的函

    2024年02月10日
    浏览(31)
  • 一文了解什么是WebSocket

    WebSocket 允许我们创建“实时”应用程序,与传统 API 协议相比,该应用程序速度更快且开销更少。​ 一、 WebSocket 是如何工作的 按照传统的定义,WebSocket是一种双工协议,主要用于客户端-服务器通信通道。它本质上是双向的,这意味着通信在客户端与服务器之间来回发生。

    2024年02月07日
    浏览(23)
  • 一文了解Docker的用法

    Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源。 Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。 容器是完全使用沙箱机制,相互之间不会有任何接口(类似

    2024年02月11日
    浏览(30)
  • 一文了解ChatGPT

    英杰社区 https://bbs.csdn.net/topics/617804998        OpenAI最近发布了一款名为ChatGPT的聊天机器人模型,它受到了广泛的关注和赞誉。ChatGPT以一种更贴近人类对话方式进行交互,可以回答问题、承认错误、挑战不正确的前提、拒绝不适当的请求等。它提供高质量的回答,并且与用

    2024年02月11日
    浏览(29)
  • 一文了解Servlet

    1、什么是Servlet Servlet是Java提供的一门动态web资源开发技术 Servlet是JavaEE规范之一,其实就是一个接口,将来我们需要定义Servlet接口,并由web服务器运行Servlet 2、Servlet快速入门 创建web项目,导入Servlet依赖坐标 创建:定义一个类,实现Servlet接口,并重写接口中的所有方法,并

    2024年01月22日
    浏览(21)
  • 【Unity】一文了解生命周期

    又新开一个坑,这个系列主要是记录Unity的干货,就不像之前那几个有点口水话了233 当然我会改正 时隔半个月 经历了开学 换教室等等一系列杂七杂八的事情也算步入正轨了~ 没杂七杂八的介绍什么,不水字数,直接开干!(暴论) 编写顺序会严格按照真实的生命周期顺序

    2023年04月22日
    浏览(25)
  • 一文了解SmartSE

    ​ 你或许没有听说过SmartSE,但你一定听说过“Virtual Electronic”,也就是“V-ECU”,虚拟ECU。2020年,ProSTEP iViP协会的SmartSE项目组出版了白皮书,对虚拟ECU做了详尽介绍。 ProSTEP iViP协会成立于1993年,来自老牌工业强国德国,总部位于德国中西部城市达姆施塔特,最早由38家工业

    2024年02月13日
    浏览(14)
  • 一文简单了解kudu

    提起大数据存储,我们很容易想到HDFS,HDFS上的列式存储技术Apache Parquet,以KV形式存储半结构化数据的Apache Hbase。对于列式存储,一方面体现在存储上能节约空间、减少 IO,另一方面依靠列式数据结构做了计算上的优化。 事实上,以上的这些存储技术都存在着一定的局限性。

    2023年04月09日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包