LimitedReader只读取一次。

huangapple go评论68阅读模式
英文:

LimitedReader reads only once

问题

我正在尝试通过学习gopl书籍来理解Go语言。在尝试实现LimitReader函数时遇到了困难。我意识到我有两个问题,让我分开来解释。

第一个问题

来自官方文档的描述是这样说的:

> LimitedReader从R中读取数据,但限制返回的数据量为N个字节。每次调用Read都会更新N以反映剩余的新数量。当N <= 0或底层的R返回EOF时,Read返回EOF。

好的,所以我的理解是我可以多次从io.Reader类型中读取,但是我始终只能限制在N个字节。运行这段代码给我展示了不同的结果:

package main

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

func main() {
	r := strings.NewReader("some io.Reader stream to be read\n")
	lr := io.LimitReader(r, 4)
	b := make([]byte, 7)
	n, err := lr.Read(b)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("Read %d bytes: %s\n", n, b)

	b = make([]byte, 5)
	n, _ = lr.Read(b)
	// If removed because EOF
	fmt.Printf("Read %d bytes: %s\n", n, b)
}
// Output:

// Read 4 bytes: some
// Read 0 bytes:
// I expect next 4 bytes instead

看起来这种类型的对象只能读取一次。不太确定,但也许可以将io.go源代码中的这一行改为l.N = 0。主要问题是为什么这段代码与文档描述不一致?

第二个问题

当我在解决第一个问题时,我尝试显示当前的N值。如果我将fmt.Println(lr.N)放在上面的代码中,它无法编译,报错lr.N undefined (type io.Reader has no field or method N)。我意识到我仍然不理解Go语言中的接口概念。

这是我的观点(基于上面的代码)。使用io.LimitReader函数我创建了LimitedReader对象(参见源代码)。由于这个对象包含了具有正确签名的Read方法,它的接口类型是io.Reader。这就是为什么io.LimitReader返回io.Reader的原因,对吗?好的,一切都很顺利。

问题是:为什么无法访问lr.N?根据我正确理解的书籍,接口类型只要求数据类型包含某些方法。没有更多的要求。

英文:

I'm trying to understand Go by studying gopl book. I'm stuck when trying to implement the LimitReader function. I realized that I have two problems so let me separate them.

First issue

The description from official doc is saying that:

> A LimitedReader reads from R but limits the amount of data returned to just N bytes. Each call to Read updates N to reflect the new amount remaining. Read returns EOF when N <= 0 or when the underlying R returns EOF.

OK, so my understanding is that I can read from io.Reader type many times but I will be always limited to N bytes. Running this code shows me something different:

package main

import (
	&quot;fmt&quot;
	&quot;io&quot;
	&quot;log&quot;
	&quot;strings&quot;
)

func main() {
	r := strings.NewReader(&quot;some io.Reader stream to be read\n&quot;)
	lr := io.LimitReader(r, 4)
	b := make([]byte, 7)
	n, err := lr.Read(b)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf(&quot;Read %d bytes: %s\n&quot;, n, b)

	b = make([]byte, 5)
	n, _ = lr.Read(b)
	// If removed because EOF
	fmt.Printf(&quot;Read %d bytes: %s\n&quot;, n, b)
}
// Output:

// Read 4 bytes: some
// Read 0 bytes:
// I expect next 4 bytes instead

It seems that this type of object is able to read only once. Not quite sure but maybe this line in io.go source code could be changed to l.N = 0. The main question is why this code is inconsistent with doc description?

Second issue

When I've struggled with the first issue I was trying to display current N value. If I put fmt.Println(lr.N) to the code above it cannot be compiled lr.N undefined (type io.Reader has no field or method N). I realized that I still don't understand Go interfaces concept.

Here is my POV (based on listing above). Using io.LimitReader function I create LimitedReader object (see source code). Due to the fact that this object contains Read method with proper signature its interface type is io.Reader. That's is the reason why io.LimitReader returns io.Reader, right? OK, so everything works together.

The question is: why lr.N cannot be accessed? As I correctly understood the book, interface type only requires that data type contains some method(s). Nothing more.

答案1

得分: 3

LimitedReader 限制了可以读取的数据的总大小,而不是每次读取调用可以读取的数据量。也就是说,如果你将限制设置为4,你可以执行4次读取每次读取1个字节的操作,或者1次读取4个字节的操作,之后,所有的读取操作都将失败。

对于你的第二个问题:lr 是一个 io.Reader,所以你不能读取 lr.N。然而,你可以使用类型断言访问底层的具体类型:lr.(*io.LimitedReader).N 应该可以工作。

英文:

LimitedReader limits the total size of data that can be read, not the amount of data that can be read at each read call. That is, if you set the limit to 4, you can perform 4 reads of 1 byte, or 1 read of 4 bytes, and after that, all reads will fail.

For your second question: lr is an io.Reader, so you cannot read lr.N. However, you can access the underlying concrete type using a type assertion: lr.(*io.LimitedReader).N should work.

huangapple
  • 本文由 发表于 2023年2月19日 06:29:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/75496785.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定