目录
  • 1. 引言
  • 2. 基本说明
    • 2.1 基本定义
    • 2.2 使用示例
  • 3. 实现原理
    • 4. 使用场景
      • 5. 总结

        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个字节。然后调用 limitReader 的 Read 方法读取数据,此时将会读取数据放到缓冲区当中,程序将读取到的字节数和内容打印出来。函数运行结果如下:

        读取的字节数: 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.Body 中 Read 方法读取数据即可,不需要操心读取到下一个请求体的数据,非常方便。

        5. 总结

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

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

        基于此,完成了对io.LimitedReader 的介绍,希望对你有所帮助,更多关于Go语言io.LimitedReader类型的资料请关注其它相关文章!

        声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。