获取“bytes.Buffer does not implement io.Writer”错误消息

117

我想让一些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
我至少遇到过这个问题两次,而且在谷歌上搜索解决方案真的没有什么帮助。 - Kevin Burke
12
注意,创建bufio并非必要。只需使用&b作为io.Writer即可。 - Vivien
3个回答

182

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

import "bufio"
import "bytes"

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

7
我遇到了这个问题,我很想知道为什么会出现这种情况。我对Go语言中的指针不是很熟悉。 - hourback
2
谢谢Kevin,这个简单的错误让我浪费了一个小时的时间,直到我谷歌搜索才解决。 :) - Nelo Mitranim
11
这与接口实现的方式有关。在Go语言中,有两种接口实现方式:值接收器和指针接收器。如果使用值接收器来实现接口,则两种方式都可以;但如果使用指针接收器来实现接口,则必须传递指向该值的指针才能使用接口。这很特别,但也很合理,因为写入者必须改变缓冲区以跟踪其写入位置。 - John Leidegren
2
这是错误的答案!newwriter有自己的[]byte缓冲区,如果b缓冲区太大,它不会捕获它。如果您尝试使用b,则无法获得完整内容。 - user1971598
缓冲区的指针(&b)已经是一个写入器!-请查看@aQua的答案,他的答案应该被选中。 - Alex Medveshchek

42
package main

import "bytes"
import "io"

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

您无需使用"bufio.NewWriter(&b)"来创建一个io.Writer。&b本身就是一个 io.Writer。


4
这应该是正确的答案。如果你试图从缓冲区创建一个新的写入器,你将无法直接获取缓冲区字节,这会使事情变得更加复杂。 - onetwopunch
1
我想知道这是在干什么?它只是检查b是否实现了Writer接口吗? _ = io.Writer(&b) - Aki
我认为上面的答案中漏掉了一个小细节,应该使用变量而不是“_”。该变量将是一个io.Writer接口到&b。然后,您将该变量传递给任何接受io.Writer的函数。 - Allen Hamilton

14

只需要使用:

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没有实现io.Writer(Write方法具有指针接收器)


一些想法,Go使用 按值传递,如果我们将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.
}

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接