一文了解 io.LimitedReader类型

这篇具有很好参考价值的文章主要介绍了一文了解 io.LimitedReader类型。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. 引言

io.LimitedReader 提供了一个有限的读取功能,能够手动设置最多从数据源最多读取的字节数。本文我们将从 io.LimitedReader 的基本定义出发,讲述其基本使用和实现原理,其次,再简单讲述下具体的使用场景,基于此来完成对io.LimitedReader 的介绍。

2. 基本说明

2.1 基本定义

io.LimitedReader 是Go语言提供的一个Reader类型,其包装了了一个io.Reader 接口,提供了一种有限的读取功能。io.LimitedReader的基本定义如下:

type LimitedReader struct {
   R Reader // underlying reader
   N int64  // max bytes remaining
}

func (l *LimitedReader) Read(p []byte) (n int, err error) {}

LimitedReader结构体中包含了两个字段,其中R 为底层Reader, 数据都是从Reader 当中读取的,而 N 则代表了剩余最多可以读取的字节数。同时也提供了一个Read 方法,通过该方法来实现对数据进行读取,在读取过程中 N 的值会不断减小。

通过使用io.LimitedReader, 我们可以控制从底层读取器读取的字节数,避免读取到不应该读取的数据,这个在某些场景下非常有用。

同时Go语言还提供了一个函数,能够使用该函数,创建出一个io.LimitedReader 实例,函数定义如下:

func LimitReader(r Reader, n int64) Reader { return &LimitedReader{r, n} }

我们可以通过该函数创建出一个LimitedReader 实例,也能够提升代码的可读性。

2.2 使用示例

下面我们展示如何使用io.LimitedReader 限制读取的字节数,代码示例如下:

package main

import (
        "fmt"
        "io"
        "strings"
)

func main() {
        // 创建一个字符串作为底层读取器
        reader := strings.NewReader("Hello, World!")

        // 创建一个LimitedReader,限制最多读取5个字节
        limitReader := io.LimitReader(reader, 5)

        // 使用LimitedReader进行读取操作
        buffer := make([]byte, 10)
        n, err := limitReader.Read(buffer)

        if err != nil && err != io.EOF {
                fmt.Println("读取错误:", err)
                return
        }

        fmt.Println("读取的字节数:", n)
        fmt.Println("读取的内容:", string(buffer[:n]))
}

在上面示例中,我们使用字符串创建了一个底层Reader,然后基于该底层Reader创建了一个io.LimitedReader,同时限制了最多读取5个字节。然后调用 limitReaderRead 方法读取数据,此时将会读取数据放到缓冲区当中,程序将读取到的字节数和内容打印出来。函数运行结果如下:

读取的字节数: 5
读取的内容: Hello

这里读取到的字节数为5,同时也只返回了前5个字符。通过这个示例,我们展示了使用io.LimitedReader 限制从底层数据源读取数据数的方法,其实只需要使用io.LimitedReader对源Reader 进行包装,同时声明最多读取的字节数即可。

3. 实现原理

在了解了io.LimitedReader的基本定义和使用后,下面我们来对io.LimitedReader的实现原理进行基本说明,通过了解其实现原理,能够帮助我们更好得理解和使用io.LimitedReader

io.LimitedReader 的实现比较简单,我们直接看其代码的实现:

func (l *LimitedReader) Read(p []byte) (n int, err error) {
   // N 代表剩余可读数据长度,如果小于等于0,此时直接返回EOF
   if l.N <= 0 {
      return 0, EOF
   }
   // 传入切片长度 大于 N, 此时通过 p = p[0:l.N] 修改切片长度,保证切片长度不大于 N
   if int64(len(p)) > l.N {
      p = p[0:l.N]
   }
   // 调用Read方法读取数据,Read方法最多读取 len(p) 字节的数据
   n, err = l.R.Read(p)
   // 修改 N 的值
   l.N -= int64(n)
   return
}

其实io.LimitedReader的实现还是比较简单的,首先,它维护了一个剩余可读字节数N,也就是LimitedReader 中的N 属性,该值最开始是由用户设置的,之后在不断读取的过程 N 不断递减,直到最后变小为0。

然后LimitedReader 中读取数据,与其他Reader 一样,需要用户传入一个字节切片参数p ,为了避免读取超过剩余可读字节数 N 的字节数,此时会比较len(p)N 的值,如果切片长度大于N,此时会使用p = p[0:l.N] 修改切片的长度,通过这种方式,保证最多只会读取到N 字节的数据。

4. 使用场景

当我们需要限制从数据源读取到的字节数时,亦或者在某些场景下,我们只需要读取数据的前几个字节或者特定长度的数据,此时使用io.LimitedReader 来实现比较简单方便。

一个经典的例子,其实是net/http 库解析HTTP请求时对io.LimitedReader的使用,通过其限制了读取的字节数。

当客户端发送HTTP请求时,可以设置头部字段 Content-Length 字段的值,通过该字段声明请求体的长度,服务端就可以根据Content-Length 头部字段的值,确定请求体的长度。服务端在读取请求体数据时,不能读取超过Content-Length 长度的数据,因为后面的数据可能是下一个请求的数据,这里通过io.LimitedReader 来确保不会读取超出Content-Length 指定长度的字节数是非常合适的,而当前net/http 库的实现也确实如此。下面是其中设置请求体的相关代码:

// 根据不同的编码类型来对 t.Body 进行设置
switch {
    // 分块编码
    case t.Chunked:
       // 忽略
    case realLength == 0:
       t.Body = NoBody
    // content-length 编码方式
    case realLength > 0:
       t.Body = &body{src: io.LimitReader(r, realLength), closing: t.Close}
    default:
       // realLength < 0, i.e. "Content-Length" not mentioned in header
       // 忽略
}

这里realLength 便是通过Content-length 头部字段来获取的,能够取到值,此时便通过io.LimitedReader 来限制HTTP请求体数据的读取。

后续执行真正的业务流程时,此时直接调用t.BodyRead 方法读取数据即可,不需要操心读取到下一个请求体的数据,非常方便。

5. 总结

io.LimitedReader 是Go语言标准库提供的一个结构体类型,能够限制从数据源读取到的字节数。 我们先从io.LimitedReader的基本定义出发,之后通过一个简单的示例,展示如何使用io.LimitedReader 来实现读取数据数的限制。

接着我们讲述了io.LimitedReader函数的实现原理,通过对这部分内容的讲述,加深了我们对其的理解。最后我们简单讲述了io.LimitedReader 的使用场景,当我们需要限制从数据源读取到的字节数时,亦或者在某些场景下,我们只需要读取数据的前几个字节或者特定长度的数据时,使用io.LimitedReader 是非常合适的。

基于此,完成了对io.LimitedReader 的介绍,希望对你有所帮助。文章来源地址https://www.toymoban.com/news/detail-548562.html

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

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

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

相关文章

  • 【⑬MySQL】· 一文了解数据类型(一)

    ✨欢迎来到小K的MySQL专栏,本节将为大家带来MySQL数据类型简介 | 整数 | 浮点 | 定点 | 时间/日期类型的分享 ✨ 0.数据类型简介 数据类型(data_type)是指系统中所允许的数据的类型。MySQL 数据类型定义了列中可以存储什么数据以及该数据怎样存储的规则。 数据库中的每个列都

    2024年02月11日
    浏览(28)
  • 一文了解 | 系统测试与集成测试有哪些类型和优势?

    作者的话 在软件开发生命周期(SDLC)中,每个软件都要经历多次质量检查,从而确保产品质量。但说起来容易做起来难。虽然敏捷框架改善了测试过程中的沟通和协作,但许多有经验的测试人员在测试过程中仍然会遇到不确定性。 他们知道集成测试在系统测试之前,但发现

    2024年02月13日
    浏览(29)
  • 【JAVA】一文带你了解java的数据类型与变量

    作者主页:paper jie的博客 本文作者:大家好,我是paper jie,感谢你阅读本文,欢迎一建三连哦。 本文录入于《JAVASE语法系列》专栏,本专栏是针对于大学生,编程小白精心打造的。笔者用重金(时间和精力)打造,将javaSE基础知识一网打尽,希望可以帮到读者们哦。 其他专栏

    2024年02月14日
    浏览(30)
  • 一文带你了解:Linux 文件系统+文件系统相关 Shell 命令+文件系统类型

    本篇文章是记录我在学习Linux时,有关Linux 文件系统的学习。 操作系统的基本功能之一就是文件管理,而文件的管理是由文件系统来完成的。 Linux 支持多种文件系统,接下来我们就来一起了解 Linux 下的 文件系统、文件系统类型、文件系统结构和文件系统相关 Shell 命令。 有

    2024年02月22日
    浏览(35)
  • 【MySQL】数据库中这么多数据类型你真的了解吗?一文看懂不同数据类型有何区别

    创建表t1,将name列数据类型设置为要tinyint 插入属性值:由于这里是tinyint类型,取值范围是【-128–127】,当插入这个范围内的数据显示成功,范围之外失败 使用tinyint unsigned类型创建表t2 无符号类型取值范围【0,255】,这点与C/C++一样 2.1.1 小结 MySQL对于数据类型不合法行为采

    2024年02月13日
    浏览(29)
  • 一文了解什么是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)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包