IO 通道与读取器/写入器

Posted

技术标签:

【中文标题】IO 通道与读取器/写入器【英文标题】:IO channels vs reader/writer 【发布时间】:2012-11-20 00:29:51 【问题描述】:

既然 Go 有通道,我想知道为什么标准库似乎没有被设计为将它们用于 IO。

有读取器和写入器类型,但是使用通道会有什么问题?

一个函数可以返回一个字节切片通道(假设单字节,甚至单比特返回效率太低),并接受一个用于取消请求的通道和一个用于错误报告的通道。

-好奇的围棋新手。

【问题讨论】:

【参考方案1】:

我的这个包实现了 io.Reader 和 io.Writer 封装成一个通道。

或者,换句话说,它创建了一个线程安全的缓冲区。

或者,换句话说,它是一个通用管道。

https://github.com/latitov/milkthisbuffer

【讨论】:

【参考方案2】:

我认为io.Readerio.Writer 存在的另一个原因是因为它们在单线程级别上运行良好;通道几乎专门用于 goroutine 间通信或多线程模型。在某些情况下,您可以互换使用它们,但它们旨在解决 2 个不同的挑战。 io.Readerio.Writer 也有 EOF 的概念,它不能轻易地用通道复制,除非你在通道上分层一个单独的协议——这当然是一种矫枉过正。 附言关闭通道与 EOF 也不一样,因为关闭通道会阻止它在将来被使用。

【讨论】:

【参考方案3】:

Channel 非常适合 goroutine 之间的通信。当一个程序做一些简单的事情时,例如读取标准输入,对流做一些事情并将结果输出到标准输出 - 然后使用通道是一种过度杀伤,不必要地损害性能。

只要标准库在某些地方没有提供特定于 goroutine 相互通信的东西,就没有充分的理由对简单的操作进行建模,例如 io.Readerio.Writer 使用通道,分别具有基于通道的方法集 (API)。

此外,在需要时,可以将简单的实现包装在通道中,而相反,将通道实现“解包”回其原语是不可能的。此外,Go 作者显然喜欢明确性,这导致性能瓶颈没有被隐藏(并且令人惊讶)。

【讨论】:

所以我认为您的观点有两个方面:1) 在这种情况下,通道将成为性能瓶颈,2) 通道会隐藏 IO,而设计人员不喜欢这样。对读取器/写入器与通道进行性能测量以了解实际的性能损失将是很有趣的——当然要意识到编译器可以针对简单的情况进行优化,并且随着时间的推移优化将变得更加复杂。 Rob Pike 谈到了渠道的性能优化机会。

以上是关于IO 通道与读取器/写入器的主要内容,如果未能解决你的问题,请参考以下文章

深入Java网络编程与NIO

如何使用套接字通道读取和写入数据并接受连接

Java NIO 读取文件写入文件读取写入混合

NIO

Java 文件IO写入读取四种方法

[Java] 非阻塞IO