【问题标题】:Why is there no RuneWriter interface in Go's io package?为什么 Go 的 io 包中没有 RuneWriter 接口?
【发布时间】:2015-05-20 04:19:53
【问题描述】:

Go's io package 包含(除其他外)以下接口:

type ByteReader interface {
        ReadByte() (c byte, err error)
}

type ByteScanner interface {
        ByteReader
        UnreadByte() error
}

type ByteWriter interface {
        WriteByte(c byte) error
}

type RuneReader interface {
        ReadRune() (r rune, size int, err error)
}

type RuneScanner interface {
        RuneReader
        UnreadRune() error
}

但是没有RuneWriter接口:

type RuneWriter interface {
        WriteRune(r rune) (size int, err error)
}

RuneWriter 丢失是否有原因?

【问题讨论】:

  • 如果你需要类似的东西,那么在你自己的代码/包中定义它。在许多地方,标准包只定义了他们使用/需要的东西,而不是完整的一套。据我所知,bufio.Reader 是标准包中唯一可以实现RuneWriter 的东西(bufio.Reader 有许多其他方法也不属于任何接口)。
  • @DaveC:但他们不应该定义他们期望用户需要什么,而不仅仅是他们自己需要什么吗?
  • 这意味着猜测任何地方的任何用户可能需要什么。接口很容易根据需要定义。将 RuneWriter 添加到 io 包中没有任何帮助。
  • 正如我所说,如果你的代码中有一个地方你想调用类似WriteRune 的东西,你可以a)制作你自己的接口并接受它作为参数或b)接受io.Reader 参数,如果对您自己的接口的类型断言失败,则将其包装为bufio.Reader。由于 bufio.Reader 是标准包中唯一实现它的东西(a)有效地强制调用者包装在 bufio.Reader (或他们自己的类似版本)。
  • 例如看看像compress/flate.NewReader 这样的东西just that

标签: types interface go io


【解决方案1】:

Go 作者根据需要定义接口。他们没有定义一个接口来填充可能的方法网格。此策略有助于使标准库保持小而简单。

我认为他们的结论是不需要 RuneWriter 接口,因为他们在标准包或他们维护的其他包中不需要它。

Go 团队之外没有对界面的需求。问题跟踪器、邮件列表或 irc 频道的可用记录历史上没有对接口的请求。

问题中引用的其他接口用于标准包或Go作者维护的其他包中。

您可以在自己的包或代码中定义接口。这是 Go 独有的一个非常有用的功能。

【讨论】:

  • “Go 作者还没有看到对 RuneWriter 接口的需求。”好吧,这就是我的问题:为什么他们没有看到需要? “标准包或他们维护的任何子回购包中都不需要它。”但 ByteWriter 也不是。
  • 是的,我可以定义我自己的接口,但是在标准库中拥有它的好处在于它使第三方库之间的兼容性比他们都必须定义他们的拥有。
  • 但您不必为兼容的接口使用相同的名称。我可以做到type Foobar interface { Read([]byte) (int,error) } 并且我的 Foobar 接口与io.Reader 或任何其他人的等效接口完全互操作(例如,我可以使函数获取或返回我的接口,而其他函数可以传递或分配给io.Reader)。重要的是方法签名而不是接口本身。
  • ByteWriter 在标准库的四个或五个位置使用。
  • 再一次,看看标准库中他们自己定义临时接口的地方的例子(就像我之前给出的压缩包示例)。将这些接口集“标准化”是没有意义的。
【解决方案2】:

只是对 Be Bop 的回答的一个小补充:

接口对于定义泛型函数很有用。例如。 func f(foo interface { Foo() }) 声明类似“我是函数 f,如果你给我一些我可以 Foo() 使用的东西,我会做得很好。”

现在考虑像RuneScanner 这样的接口。 RuneScanner 提供了非平凡的方法,尤其是 UnreadRune,它不能被“低级”的东西轻易模拟。

RuneWriter 接口有什么用处?定义一个函数func g(rw RuneWriter),它宣称自己是“给我一些我可以写符文的东西,我会做我的工作!” ?但是没有真正的需要,因为这可以通过标准方法简单地模拟:将其定义为 func g(r io.Writer) 并在里面使用 fmt.Fprintf(r ...)。 如果你想写符文,你必须有能力写 1 到 6 (?) 个字节,这就是 io.Writer 提供的。所以不需要RuneWriter

通过引入RuneWriter 会使代码更具可读性或更安全吗?可能不会:函数func g(rw RuneWriter) 明确声明它只希望将 runes 写入其参数。这很好,但对编写更好的程序并没有真正的帮助。符文是 1 到 6 个字节,g 做出的唯一额外承诺是“写入我的参数的任何内容都将是有效的 UTF-8 编码流”。这是一个非常肤浅的承诺。

【讨论】:

    猜你喜欢
    • 2011-05-12
    • 1970-01-01
    • 2011-04-24
    • 1970-01-01
    • 2014-03-07
    • 2014-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多