Obtener el mensaje de error "bytes.Buffer no implementa io.Writer"

98

Estoy tratando de que algún objeto Go implemente io.Writer, pero escribe en una cadena en lugar de un archivo o un objeto similar a un archivo. Pensé bytes.Bufferque funcionaría ya que se implementa Write(p []byte). Sin embargo, cuando intento esto:

import "bufio"
import "bytes"

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

Obtuve el siguiente error:

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)

Estoy confundido, ya que claramente implementa la interfaz. ¿Cómo resuelvo este error?

Kevin Burke
fuente
2
Me he encontrado con este problema al menos dos veces, y buscar una solución en Google fue realmente inútil.
Kevin Burke
11
Tenga en cuenta que la creación de un bufio no es necesaria. Simplemente use & b como io.Writer
Vivien

Respuestas:

153

Pase un puntero al búfer, en lugar del búfer en sí:

import "bufio"
import "bytes"

func main() {
    var b bytes.Buffer
    foo := bufio.NewWriter(&b)
}
Kevin Burke
fuente
4
Me encontré con esto y estaría interesado en saber por qué ese es el caso. No estoy familiarizado con los punteros en Go.
Hora de regreso
1
Gracias Kevin, este simple error tomó una hora de mi tiempo hasta que busqué en Google. :)
Nelo Mitranim
7
@hourback tiene que ver con la forma en que se implementa la interfaz. De hecho, hay formas de implementar una interfaz en Go. Ya sea con receptores de valor o puntero. Creo que este es un giro realmente peculiar de Go. Si la interfaz se implementa usando receptores de valor, cualquier forma está bien, pero si la interfaz se implementa usando receptores de puntero, debe pasar un puntero al valor si tiene la intención de usar la interfaz. Tiene sentido ya que el escritor tiene que mutar el búfer para realizar un seguimiento de dónde está la cabeza del escritor.
John Leidegren
23
package main

import "bytes"
import "io"

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

No es necesario utilizar "bufio.NewWriter (& b)" para crear un io.Writer. & b es un escritor io.Writer.

agua
fuente
Esta debería ser la respuesta correcta. Si intenta crear un nuevo escritor fuera del búfer, no podrá obtener los bytes del búfer directamente, lo que complica mucho las cosas.
onetwopunch
8

Solo usa

foo := bufio.NewWriter(&b)

Porque la forma en que bytes.Buffer implementa io.Writer es

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

Es b *Buffer, no b Buffer. (También creo que es extraño porque podemos llamar a un método mediante una variable o su puntero, pero no podemos asignar un puntero a una variable de tipo que no sea puntero).

Además, el indicador del compilador no es lo suficientemente claro:

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


Algunas ideas, ve a usar Passed by value, si pasamos ba buffio.NewWriter(), en NewWriter (), es un nuevo b(un nuevo búfer), no el búfer original que definimos, por lo tanto, necesitamos pasar la dirección &b.

Adjuntar de nuevo, bytes.Buffer está definido:

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.
}

usando passed by value, la nueva estructura de búfer pasada es diferente de la variable de búfer de origen.

wmlhust
fuente