Отримання повідомлення про помилку "bytes.Buffer не реалізує io.Writer"


98

Я намагаюся, щоб якийсь об'єкт 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
Я щонайменше двічі зіткнувся з цією проблемою, і Гуглінг для вирішення справді не допомагав.
Кевін Берк,

11
Зауважте, що створення буфіо не потрібно. Просто використовуйте & b як io.Writer
Vivien

Відповіді:


153

Передайте вказівник на буфер замість самого буфера:

import "bufio"
import "bytes"

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

4
Я зіткнувся з цим і хотів би дізнатися, чому це так. Мені досить незнайомі вказівники Go.
зворотний час

1
Дякую Кевіне, ця проста помилка зайняла годину мого часу, поки я не погуглив це. :)
Нело Мітранім

7
@hourback це пов'язано з тим, як реалізований інтерфейс. Насправді є способи реалізації інтерфейсу в Go. Або із приймачами значення, або з вказівниками. Я думаю, що це справді своєрідний поворот до Go. Якщо інтерфейс реалізований за допомогою приймачів значень, будь-який спосіб у порядку, але якщо інтерфейс реалізований за допомогою приймачів покажчиків, вам слід передати вказівник на значення, якщо ви плануєте використовувати інтерфейс. Це має сенс, оскільки письменнику доводиться мутувати буфер, щоб відстежувати, де знаходиться його голова.
Джон Лейдегрен

23
package main

import "bytes"
import "io"

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

Вам не потрібно використовувати "bufio.NewWriter (& b)", щоб створити io.Writer. & b - це io.Writer.


Це повинна бути правильна відповідь. Якщо ви спробуєте створити новий буфер із буфера, ви не зможете безпосередньо отримати байти буфера, що значно ускладнює ситуацію.
onetwopunch

8

Просто використовуйте

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 does not implement io.Writer (Write method has pointer receiver)


Деякі ідеї. Перейдіть Passed by value, якщо ми переходимо bдо buffio.NewWriter(), в NewWriter (), це новий b(новий буфер), а не оригінальний буфер, який ми визначили, тому нам потрібно передати адресу&b .

Додайте ще раз, байти. Буфер визначено:

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

використовуючи passed by valueнову структуру буфера, що відрізняється від змінної буфера початкової.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.