我试图通过学习 gopl book 来理解 Go。我在尝试实现 LimitReader
功能时卡住了。我意识到我有两个问题,所以让我把它们分开。
第一期
官方文档的描述是这样说的:
A LimitedReader 从 R 中读取,但将返回的数据量限制为仅 N 个字节。每次调用 Read 都会更新 N 以反映新的剩余数量。当 N <= 0 or when the underlying R returns EOF.
时 Read 返回 EOF
OK,所以我的理解是我可以从 io.Reader
type 读取很多次,但我总是被限制在 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 接口的概念。
这是我的 POV(基于上面的列表)。使用 io.LimitReader
函数创建 LimitedReader
对象(参见 source code)。由于此对象包含带有适当签名的 Read
方法,因此其接口类型为 io.Reader
。这就是 io.LimitReader
返回 io.Reader
的原因,对吧?好的,所以一切都在一起。
问题是:为什么lr.N
无法访问?正如我对这本书的正确理解,接口类型只要求数据类型包含一些方法。仅此而已。
LimitedReader
限制可以读取的数据总大小,而不是每次读取调用时可以读取的数据量。也就是说,如果你设置limit为4,你可以执行4次1字节的读取,或者1次4字节的读取,之后,所有的读取都会失败。
对于你的第二个问题:lr
是一个io.Reader
,所以你不能阅读lr.N
。但是,您可以使用类型断言访问底层具体类型:lr.(*io.LimitedReader).N
应该有效。