获取"bytes.Buffer不实现io.Writer"错误消息

Kev*_*rke 84 go

我试图让一些Go对象实现io.Writer,但写入一个字符串而不是一个文件或类文件对象.我认为bytes.Buffer它会有效,因为它实现了Write(p []byte).但是,当我尝试这个:

import "bufio"
import "bytes"

func main() {
    var b bytes.Buffer
    foo := bufio.NewWriter(b)
}
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

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)
Run Code Online (Sandbox Code Playgroud)

我很困惑,因为它清楚地实现了界面.我该如何解决这个错误?

Kev*_*rke 133

将指针传递给缓冲区,而不是缓冲区本身:

import "bufio"
import "bytes"

func main() {
    var b bytes.Buffer
    foo := bufio.NewWriter(&b)
}
Run Code Online (Sandbox Code Playgroud)

  • 不要忘记在从b读取之前调用foo.Flush() (30认同)
  • @hourback它与接口的实现方式有关.实际上有一些方法可以在Go中实现一个接口.有值或指针接收器.我认为这对Go来说是一个非常特殊的转折.如果使用值接收器实现接口,则任何一种方法都可以,但如果使用指针接收器实现接口,则必须传递指向该值的指针(如果您打算使用该接口).这是有道理的,因为作者必须改变缓冲区以跟踪它的作者头部. (5认同)
  • 我遇到了这个并且有兴趣了解为什么会这样.我对Go的指针很不熟悉. (3认同)
  • 谢谢凯文,这个简单的错误花了我一个小时的时间,直到我用谷歌搜索了这个。:) (2认同)
  • 这是错误的答案!newwriter 有自己的 []byte 缓冲区,如果 b 缓冲区太大,它不会捕获它。如果您尝试使用 b,它将不具有完整的内容。 (2认同)

aQu*_*Qua 17

package main

import "bytes"
import "io"

func main() {
    var b bytes.Buffer
    _ = io.Writer(&b)
}
Run Code Online (Sandbox Code Playgroud)

您不需要使用"bufio.NewWriter(&b)"来创建io.Writer.&b是io.Writer本身.

  • 这应该是正确的答案。如果您尝试从缓冲区创建一个新的写入器,您将无法直接获取缓冲区字节,这使事情变得更加复杂。 (4认同)

小智 9

只需使用

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)
}
Run Code Online (Sandbox Code Playgroud)

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

此外,编译器提示不够清楚:

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


一些想法,去使用Passed by value,如果我们通过bbuffio.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.
}
Run Code Online (Sandbox Code Playgroud)

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