我理解Go接口的一般概念。但是,我最近正在考虑实现io.Reader
接口,这让我很困惑。我发现这篇文章并没有多大帮助。
Reader interface and the Read method in golang
首先,接受的答案是使用io.Reader
的{{1}}函数,据我所知,该函数从未实现过。其次,Read
函数如何在Read
之类的上下文中工作。它需要实现ioutil.ReadAll
接口并返回一个字节片。我不明白只返回io.Reader
和int
的内容可以处理成一片字节。
编辑:
我在疯狂的IRC频道中得到了帮助,这就是你如何实际实现一个http://play.golang.org/p/ejpUVOx8jR的答案。非常感谢go社区。 p>
编辑2:
如下所述,在strign大于缓冲区的情况下,上述实现将失败。这是一个更健全的实现http://play.golang.org/p/t4Zg8TnF33。
答案 0 :(得分:9)
您传递Read
字节切片。 Read
应该在其中放入字节。由于切片只是对数组的引用,因此更改切片的内容会更改基础数组,因此Read
的调用者只需检查它传递给它的切片。
ioutil.ReadAll
创建一个缓冲区并在其上调用ReadFrom
。 ReadFrom
重复调用Read
,增加缓冲区的大小,直到Read
通过返回io.EOF
作为错误告诉它已经用尽。 See for yourself
您链接的答案确实实现了io.Reader
界面。它声明了一种方法Read(p []byte) (n int, e error)
。这就是所需要的一切。
答案 1 :(得分:3)
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)
答案 2 :(得分:1)
请注意,您在此处Read()
方法的实施(http://play.golang.org/p/ejpUVOx8jR)不正确。您没有考虑提供的p []byte
参数的容量。您将获得超出范围的"索引"如果它小于你的测试字符串会引起恐慌(例如:http://play.golang.org/p/DhcY0hJ0c0)。
您可以考虑使用其他方法 - http://play.golang.org/p/t4Zg8TnF33。
<强>更新强> 我注意到我的实现中存在内存泄漏。固定版本在此处 - http://play.golang.org/p/9BbS54d8pb。这表明即使是一个微不足道的代码有时也不是那么简单:)