【问题标题】:Getting "bytes.Buffer does not implement io.Writer" error message获取“bytes.Buffer 未实现 io.Writer”错误消息
【发布时间】:2014-06-20 17:16:42
【问题描述】:

我正在尝试让一些 Go 对象实现 io.Writer,但写入的是字符串而不是文件或类似文件的对象。我认为bytes.Buffer 会起作用,因为它实现了Write(p []byte)。但是,当我尝试这样做时:

import "bufio"
import "bytes"

func main() {
    var b bytes.Buffer
    foo := bufio.NewWriter(b)
}

我收到以下错误:

cannot use b (type bytes.Buffer) as type io.Writer in function argument:
bytes.Buffer does not implement io.Writer (Write method has pointer receiver)

我很困惑,因为它清楚地实现了接口。如何解决此错误?

【问题讨论】:

  • 我至少遇到过两次这个问题,谷歌搜索解决方案真的没有帮助。
  • 请注意,不需要创建 bufio。只需将 &b 用作 io.Writer

标签: go


【解决方案1】:

传递一个指向缓冲区的指针,而不是缓冲区本身:

import "bufio"
import "bytes"

func main() {
    var b bytes.Buffer
    foo := bufio.NewWriter(&b)
}

【讨论】:

  • 我遇到了这个问题,并且有兴趣了解为什么会这样。我对 Go 中的指针非常陌生。
  • 谢谢凯文,这个简单的错误花了我一个小时的时间,直到我用谷歌搜索了这个。 :)
  • @hourback 它与接口的实现方式有关。实际上有一些方法可以在 Go 中实现接口。使用值或指针接收器。我认为这对 Go 来说是一个非常奇特的转折。如果接口是使用值接收器实现的,则任何一种方式都可以,但是如果接口是使用指针接收器实现的,则如果您打算使用该接口,则必须将指针传递给该值。这是有道理的,因为写入者必须改变缓冲区以跟踪写入者的头部位置。
  • 这是错误的答案! newwriter 有它自己的 []byte 缓冲区,如果 b 缓冲区太大,它不会捕获它。如果你尝试使用 b,它不会有完整的内容。
【解决方案2】:
package main

import "bytes"
import "io"

func main() {
    var b bytes.Buffer
    _ = io.Writer(&b)
}

您不需要使用“bufio.NewWriter(&b)”来创建 io.Writer。 &b 本身就是一个 io.Writer。

【讨论】:

  • 这应该是正确的答案。如果您尝试从缓冲区中创建一个新的写入器,您将无法直接获取缓冲区字节,这会使事情变得更加复杂。
  • 我想了解这是在做什么?是否只是检查 b 是否实现了 Writer 接口? _ = io.Writer(&b)
【解决方案3】:

随便用

foo := bufio.NewWriter(&b)

因为bytes.Buffer实现io.Writer的方式是

func (b *Buffer) Write(p []byte) (n int, err error) {
    ...
}
// io.Writer definition
type Writer interface {
    Write(p []byte) (n int, err error)
}

这是b *Buffer,而不是b Buffer。 (我也觉得很奇怪,我们可以通过变量或其指针调用方法,但我们不能将指针分配给非指针类型的变量。)

另外编译提示也不够清晰:

bytes.Buffer does not implement io.Writer (Write method has pointer receiver)


一些想法,Go 使用Passed by value,如果我们将b 传递给buffio.NewWriter(),在NewWriter() 中,它是一个新的b(一个新的缓冲区),而不是我们定义的原始缓冲区,因此我们需要传递地址&b


bytes.Buffer 定义为:

type Buffer struct {
    buf       []byte   // contents are the bytes buf[off : len(buf)]
    off       int      // read at &buf[off], write at &buf[len(buf)]
    bootstrap [64]byte // memory to hold first slice; helps small buffers avoid allocation.
    lastRead  readOp   // last read operation, so that Unread* can work correctly.
}

使用passed by value,传递的新缓冲区结构与原始缓冲区变量不同。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多