Das Abrufen der Fehlermeldung "bytes.Buffer implementiert io.Writer nicht"

97

Ich versuche, ein Go-Objekt io.Writer implementieren zu lassen, schreibe aber in eine Zeichenfolge anstelle einer Datei oder eines dateiähnlichen Objekts. Ich dachte, es bytes.Bufferwürde funktionieren, da es implementiert wird Write(p []byte). Wenn ich dies jedoch versuche:

import "bufio"
import "bytes"

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

Ich erhalte folgende Fehlermeldung:

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)

Ich bin verwirrt, da es die Schnittstelle klar implementiert. Wie behebe ich diesen Fehler?

Kevin Burke
quelle
2
Ich bin mindestens zweimal auf dieses Problem gestoßen, und das Googeln nach einer Lösung war wirklich nicht hilfreich.
Kevin Burke
11
Beachten Sie, dass die Erstellung eines Bufios nicht erforderlich ist. Verwenden Sie einfach & b als io.Writer
Vivien

Antworten:

153

Übergeben Sie anstelle des Puffers selbst einen Zeiger auf den Puffer:

import "bufio"
import "bytes"

func main() {
    var b bytes.Buffer
    foo := bufio.NewWriter(&b)
}
Kevin Burke
quelle
4
Ich bin darauf gestoßen und würde gerne erfahren, warum das so ist. Ich bin mit Zeigern in Go ziemlich unbekannt.
Hourback
1
Danke Kevin, dieser einfache Fehler hat eine Stunde meiner Zeit gedauert, bis ich das gegoogelt habe. :)
Nelo Mitranim
7
@hourback hat damit zu tun, wie die Schnittstelle implementiert ist. Es gibt tatsächlich Möglichkeiten, eine Schnittstelle in Go zu implementieren. Entweder mit Wert- oder Zeigerempfängern. Ich denke, das ist eine wirklich eigenartige Wendung für Go. Wenn die Schnittstelle mithilfe von Wertempfängern implementiert ist, ist dies in beiden Richtungen in Ordnung. Wenn die Schnittstelle jedoch mithilfe von Zeigerempfängern implementiert ist, müssen Sie einen Zeiger auf den Wert übergeben, wenn Sie die Schnittstelle verwenden möchten. Dies ist sinnvoll, da der Schreiber den Puffer mutieren muss, um zu verfolgen, wo sich sein Schreiberkopf befindet.
John Leidegren
23
package main

import "bytes"
import "io"

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

Sie müssen "bufio.NewWriter (& b)" nicht verwenden, um einen io.Writer zu erstellen. & b ist ein io.Writer selbst.

aQua
quelle
Dies sollte die richtige Antwort sein. Wenn Sie versuchen, einen neuen Writer aus dem Puffer zu erstellen, können Sie die Pufferbytes nicht direkt abrufen, was die Sache viel komplizierter macht.
onetwopunch vor
7

Benutz einfach

foo := bufio.NewWriter(&b)

Weil die Art und Weise, wie bytes.Buffer io.Writer implementiert, ist

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

Es ist b *Buffernicht b Buffer. (Ich finde es auch seltsam, dass wir eine Methode über eine Variable oder ihren Zeiger aufrufen können, aber wir können einer Variablen ohne Zeiger keinen Zeiger zuweisen.)

Außerdem ist die Compiler-Eingabeaufforderung nicht klar genug:

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


Einige Ideen, Go Gebrauch Passed by value, wenn wir passieren bzu buffio.NewWriter(), in NewWriter (), ist es ein neuer b(ein neuer Puffer), nicht der ursprüngliche Puffer wir definierten, damit wir die Adresse übergeben müssen &b.

Erneut anhängen, Bytes.Buffer ist definiert:

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

Bei Verwendung passed by valueunterscheidet sich die übergebene neue Pufferstruktur von der Ursprungspuffervariablen.

wmlhust
quelle