我理解Go接口的一般概念。然而,我最近正在研究实现io.Reader接口,这让我感到困惑。我发现这篇文章没有多大帮助。
Reader interface and the Read method in golang
首先,公认的答案是使用io.Reader的Read函数,据我所知,这个函数从来没有实现过。其次,Read函数在ioutil.ReadAll这样的上下文中是如何工作的。它接受实现io.Reader接口的东西,并返回一个字节切片。我不明白如何将只返回int和err的东西处理成字节切片。
编辑:
我在go-坚果IRC频道得到了帮助,这是关于如何实际实现一个http://play.golang.org/p/ejpUVOx8jR的答案。非常感谢go社区。
编辑2:
如下所述,在strign大于buffer的情况下,上面的实现将失败。这是一个更合理的实现http://play.golang.org/p/t4Zg8TnF33。
发布于 2015-01-28 00:27:20
将字节片传递给Read。Read应该在其中放入字节。由于切片只是对数组的引用,因此更改切片的内容会更改底层数组,因此Read的调用者可以只检查它传递给它的切片。
ioutil.ReadAll创建一个缓冲区并在其上调用ReadFrom。ReadFrom重复调用Read,增加缓冲区的大小,直到Read通过将io.EOF作为错误返回来告知它已耗尽为止。See for yourself。
您链接的答案确实实现了io.Reader接口。它正在声明一个方法Read(p []byte) (n int, e error)。这就是我们所需要的。
发布于 2016-11-17 06:50:31
tez提供的更新后的答案完全有效,但这里有一个我认为使用Go的copy的更简洁的替代方案
type Reader struct {
data []byte
readIndex int64
}
func (r *Reader) Read(p []byte) (n int, err error) {
if r.readIndex >= int64(len(r.data)) {
err = io.EOF
return
}
n = copy(p, r.data[r.readIndex:])
r.readIndex += int64(n)
return
}通过使用copy,您不必担心p []byte溢出。这也不会耗尽/破坏阅读器上的任何状态,而只是使用readIndex迭代它。
完整示例如下:https://play.golang.org/p/8QTECCkies
这一策略可以在Go的一些核心包中看到(即。https://golang.org/src/strings/reader.go)
发布于 2015-01-29 04:45:02
只需注意,您在此处(http://play.golang.org/p/ejpUVOx8jR)实现的Read()方法是不正确的。您没有考虑到所提供的p []byte参数的容量。如果它小于你的测试字符串(例如:http://play.golang.org/p/DhcY0hJ0c0),你会得到一个“索引超出范围”的警告。
您可以考虑一种不同的方法,比如http://play.golang.org/p/t4Zg8TnF33。
更新我注意到我的实现中有一个内存泄漏。修复的版本在这里- http://play.golang.org/p/9BbS54d8pb。这表明即使是微不足道的代码有时也不是那么微不足道:)
https://stackoverflow.com/questions/28174970
复制相似问题