`bufio.Writer`或`io.Writer`?

Ser*_*lla 1 interface go

我有一个函数将数据写入任何实现接口的Write(b []byte) (n int, err error)方法.现在在我的程序中,我写了一个实际的Conn,但遵循最佳实践(https://dave.cheney.net/2016/08/20/solid-go-design),因为我只打电话Write,我想接受最低限度实现该方法的接口.为此,我接受带接口的参数io.Writer.

由于我的功能可以非常快速地输出大量数据,我应该接受bufio.Writer吗?或者功能的消费者责任是使用缓冲编写器而不是普通编写器?什么是最佳做法?

icz*_*cza 7

创建接受的函数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))
}
Run Code Online (Sandbox Code Playgroud)

如果您创建要接受的函数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)
}
Run Code Online (Sandbox Code Playgroud)

但通常只有在"超出"需要额外功能时才应用这种包装io.Writer.