获取“ bytes.Buffer无法实现io.Writer”错误消息


98

我正在尝试使一些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)

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


2
我至少两次遇到这个问题,而Google搜索解决方案确实没有帮助。
凯文·伯克

11
请注意,不必创建bufio。只需将&b用作io.Writer
Vivien,

Answers:


153

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

import "bufio"
import "bytes"

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

4
我遇到了这个问题,并且有兴趣了解为什么会这样。我对Go中的指针不熟悉。
小时制,2014年

1
谢谢凯文,这个简单的错误花了我一个小时的时间,直到我用谷歌搜索了。:)
Nelo Mitranim 2014年

7
@hourback与接口的实现方式有关。实际上,有一些方法可以在Go中实现接口。有值接收器或指针接收器。我认为这是Go的真正特色。如果使用值接收器实现接口,则两种方法都可以,但是如果使用指针接收器实现接口,则要使用该接口,必须将指针传递给该值。这是有道理的,因为编写者必须更改缓冲区以跟踪其编写者所在的位置。
约翰·莱德格伦

23
package main

import "bytes"
import "io"

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

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


这应该是正确的答案。如果尝试在缓冲区之外创建新的编写器,则将无法直接获取缓冲区Byte,这会使事情变得更加复杂。
onetwopunch

8

只需使用

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)


一些想法,去使用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.
}

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.