golang strings.NewReader

为什么说strings.Reader类型的值可以高效地读取字符串

与strings.Builder类型恰恰相反,strings.Reader类型是为了高效读取字符串而存在的。后者的高效主要体现在它对字符串的读取机制上,它封装了很多用于在string值上读取内容的最佳实践。

strings.Reader类型的值(以下简称Reader值)可以让我们很方便地读取一个字符串中的内容。在读取的过程中,Reader值会保存已读取的字节的计数(以下简称已读计数)。

已读计数也代表着下一次读取的起始索引位置。Reader值正是依靠这样一个计数,以及针对字符串值的切片表达式,从而实现快速读取。

此外,这个已读计数也是读取回退和位置设定时的重要依据。虽然它属于Reader值的内部结构,但我们还是可以通过该值的Len方法和Size把它计算出来的

Reader值拥有的大部分用于读取的方法都会及时地更新已读计数。比如,ReadByte方法会在读取成功后将这个计数的值加1。

又比如,ReadRune方法在读取成功之后,会把被读取的字符所占用的字节数作为计数的增量。

不过,ReadAt方法算是一个例外。它既不会依据已读计数进行读取,也不会在读取后更新它。正因为如此,这个方法可以自由地读取其所属的Reader值中的任何内容。

复制代码
// 示例1。
    reader1 := strings.NewReader(
        "中文的的的SimpleNewReader returns a new Reader reading from s. " +
            "It is similar to bytes.NewBufferString but more efficient and read-only. ")
%d\n",reader1.Size()-int64(reader1.Len()))
    fmt.Printf("len:%d\n",reader1.Len()) //原始字符串长度是141
    by:= make([]byte,20)
    reader1.ReadAt(by,2) //这个方法不做计数也就是原值不变也就是len长度还是原始长度

    buf1 := make([]byte, 3) //原值偏移量+3 len长度要-3
     reader1.Read(buf1)
    fmt.Printf("len:%d value:%s\n",reader1.Len(),string(buf1))
复制代码

打印结果为

len:141
len:138 value:中 

除此之外,Reader值的Seek方法也会更新该值的已读计数。实际上,这个Seek方法的主要作用正是设定下一次读取的起始索引位置

复制代码
offset2 := int64(17)
expectedIndex := reader1.Size() - int64(reader1.Len()) + offset2
fmt.Printf("Seek with offset %d and whence %d ...\n", offset2, io.SeekCurrent)
readingIndex, _ := reader1.Seek(offset2, io.SeekCurrent)
fmt.Printf("The reading index in reader: %d (returned by Seek)\n", readingIndex)
fmt.Printf("The reading index in reader: %d (computed by me)\n", expectedIndex)
复制代码

posted on 2020-04-02 18:07  ExplorerMan  阅读(951)  评论(0编辑  收藏  举报

导航