Mendapatkan pesan error "bytes.Buffer tidak mengimplementasikan io.Writer"

98

Saya mencoba untuk menerapkan beberapa objek Go io.Writer, tetapi menulis ke string, bukan file atau objek seperti file. Saya pikir bytes.Bufferakan berhasil karena diimplementasikan Write(p []byte). Namun ketika saya mencoba ini:

import "bufio"
import "bytes"

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

Saya mendapatkan kesalahan berikut:

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)

Saya bingung, karena ini mengimplementasikan antarmuka dengan jelas. Bagaimana cara mengatasi kesalahan ini?

Kevin Burke
sumber
2
Saya telah mengalami masalah ini setidaknya dua kali, dan mencari solusi di Google benar-benar tidak membantu.
Kevin Burke
11
Perhatikan bahwa pembuatan bufio tidak perlu. Cukup gunakan & b sebagai io.Writer
Vivien

Jawaban:

153

Teruskan pointer ke buffer, bukan ke buffer itu sendiri:

import "bufio"
import "bytes"

func main() {
    var b bytes.Buffer
    foo := bufio.NewWriter(&b)
}
Kevin Burke
sumber
4
Saya mengalami ini dan akan tertarik untuk mempelajari mengapa demikian. Saya sangat tidak terbiasa dengan petunjuk di Go.
hourback
1
Terima kasih Kevin, kesalahan sederhana ini memakan waktu satu jam dari waktu saya sampai saya mencari di Google. :)
Nelo Mitranim
7
@hourback itu ada hubungannya dengan cara antarmuka diimplementasikan. Sebenarnya ada cara untuk mengimplementasikan antarmuka di Go. Baik dengan penerima nilai atau penunjuk. Saya pikir ini adalah twist yang sangat aneh untuk Go. Jika antarmuka diimplementasikan menggunakan penerima nilai, salah satu caranya adalah OK tetapi jika antarmuka diimplementasikan menggunakan penerima penunjuk, Anda harus meneruskan penunjuk ke nilai jika Anda ingin menggunakan antarmuka. Masuk akal karena penulis harus mengubah buffer untuk melacak di mana kepala penulisnya.
John Leidegren
23
package main

import "bytes"
import "io"

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

Anda tidak perlu menggunakan "bufio.NewWriter (& b)" untuk membuat io.Writer. & b adalah io.Writer itu sendiri.

aQua
sumber
Ini harus menjadi jawaban yang benar. Jika Anda mencoba membuat penulis baru dari buffer, Anda tidak akan dapat mengambil buffer Bytes secara langsung, yang membuat segalanya menjadi lebih rumit.
onetwopunch
8

Gunakan saja

foo := bufio.NewWriter(&b)

Karena cara bytes.Buffer mengimplementasikan io.Writer adalah

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

Ini b *Buffer, tidak b Buffer. (Saya juga berpikir itu aneh karena kita dapat memanggil metode dengan variabel atau penunjuknya, tetapi kita tidak dapat menetapkan penunjuk ke variabel jenis non-penunjuk.)

Selain itu, prompt kompilator tidak cukup jelas:

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


Beberapa ide, Go gunakan Passed by value, jika kita meneruskan bke buffio.NewWriter(), di NewWriter (), ini adalah baru b(buffer baru), bukan buffer asli yang kita definisikan, oleh karena itu kita perlu meneruskan alamatnya &b.

Tambahkan lagi, byte.Buffer didefinisikan:

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

menggunakan passed by value, struct penyangga baru yang diteruskan berbeda dari variabel penyangga asal.

wmlhust.dll
sumber