我有一个函数可以将数据写入任何实现接口(interface)的对象,该接口(interface)使用 Write(b []byte) (n int, err error)
方法。现在在我的程序中,我写入一个实际的 Conn
,但遵循最佳实践 (https://dave.cheney.net/2016/08/20/solid-go-design),并且因为我只调用 Write
,所以我想接受最小接口(interface)实现该方法。为此,我接受了接口(interface)为 io.Writer
的参数。
由于我的函数可以非常快速地输出大量数据,我应该接受 bufio.Writer
吗?还是函数的消费者有责任使用缓冲编写器而不是普通编写器?什么是最佳做法?
最佳答案
创建您的函数以接受 io.Writer
,并记录它将写入大量数据,因此 bufio.Writer
或建议使用类似的结构。
不要将您函数的用户限制为 bufio.Writer
,因为您只使用 io.Writer
的功能。用户也可能有其他对他们来说足够的 io.Writer
的“缓冲”实现。
不要决定什么对图书馆的用户有好处,让他们决定什么对他们有好处。如果用户发现 bufio.Writer
有用或比他们的 io.Writer
实现更好,他们总是可以将它包装在 bufio.Writer
中并通过那(只需使用 bufio.NewWriter(w)
)。
如果您创建接受io.Writer
的函数,用户始终可以使用一行实用函数非常轻松地添加包装功能:
func wrapAndPass(w io.Writer) {
yourFunction(bufio.NewWriter(w))
}
如果您创建函数来接受 bufio.Writer
,那么用户就无法撤消这种“包装”。用户将被迫始终创建并传递 bufio.Writer
,无论是否需要。
您也可以选择提供两个 函数:采用io.Writer
的原始函数,以及上面的包装和传递实用函数。如果这样做,最好检查传递的编写器是否已经是 *bufio.Writer
,在这种情况下应避免换行。像这样:
func wrapIfNeededAndPass(w io.Writer) {
if _, ok := w.(*bufio.Writer); !ok {
w = bufio.NewWriter(w)
}
yourFunction(w)
}
但通常这种包装仅在需要“超出”io.Writer
的额外功能时应用。
关于go - `bufio.Writer` 还是 `io.Writer`?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48115577/