英文:
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 (
"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
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论