Ottenere il messaggio di errore "bytes.Buffer non implementa io.Writer"


98

Sto cercando di fare in modo che un oggetto Go implementi io.Writer, ma scrive su una stringa anziché su un file o su un oggetto simile a un file. Ho pensato che bytes.Bufferavrebbe funzionato poiché implementa Write(p []byte). Tuttavia, quando provo questo:

import "bufio"
import "bytes"

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

Ottengo il seguente errore:

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)

Sono confuso, poiché implementa chiaramente l'interfaccia. Come risolvo questo errore?


2
Mi sono imbattuto in questo problema almeno due volte e cercare una soluzione su Google è stato davvero inutile.
Kevin Burke

11
Nota che la creazione di un bufio non è necessaria. Usa & b come io.Writer
Vivien

Risposte:


153

Passa un puntatore al buffer, invece del buffer stesso:

import "bufio"
import "bytes"

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

4
Mi sono imbattuto in questo e sarei interessato a scoprire perché è così. Non ho abbastanza familiarità con i puntatori in Go.
ritorno del

1
Grazie Kevin, questo semplice errore ha richiesto un'ora del mio tempo prima di averlo cercato su Google. :)
Nelo Mitranim

7
@hourback ha a che fare con il modo in cui l'interfaccia è implementata. In realtà ci sono modi per implementare un'interfaccia in Go. O con ricevitori di valore o puntatore. Penso che questa sia una svolta davvero particolare per Go. Se l'interfaccia è implementata usando ricevitori di valore in entrambi i modi va bene, ma se l'interfaccia è implementata usando ricevitori di puntatori devi passare un puntatore al valore se intendi usare l'interfaccia. Ha senso dal momento che l'autore deve modificare il buffer per tenere traccia di dove si trova a capo dello scrittore.
John Leidegren

23
package main

import "bytes"
import "io"

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

Non è necessario utilizzare "bufio.NewWriter (& b)" per creare un io.Writer. & b è un io.Writer stesso.


Questa dovrebbe essere la risposta giusta. Se provi a creare un nuovo writer dal buffer, non sarai in grado di recuperare direttamente i byte del buffer, il che rende le cose molto più complicate.
pranzo il

8

Basta usare

foo := bufio.NewWriter(&b)

Perché il modo in cui bytes.Buffer implementa 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)
}

Non lo b *Bufferè b Buffer. (Penso anche che sia strano perché possiamo chiamare un metodo da una variabile o dal suo puntatore, ma non possiamo assegnare un puntatore a una variabile di tipo non puntatore.)

Inoltre, il prompt del compilatore non è abbastanza chiaro:

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


Alcune idee, usate da Go Passed by value, se passiamo ba buffio.NewWriter(), in NewWriter (), è un nuovo b(un nuovo buffer), non il buffer originale che abbiamo definito, quindi dobbiamo passare l'indirizzo &b.

Aggiungi di nuovo, byte. Il buffer è definito:

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

utilizzando passed by value, la nuova struttura del buffer passata è diversa dalla variabile del buffer di origine.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.