Nhận thông báo lỗi “byte.Buffer không triển khai io.Writer”


98

Tôi đang cố gắng để một số đối tượng Go triển khai io.Writer, nhưng ghi vào một chuỗi thay vì một tệp hoặc đối tượng giống tệp. Tôi nghĩ bytes.Buffersẽ hoạt động kể từ khi nó được triển khai Write(p []byte). Tuy nhiên khi tôi thử điều này:

import "bufio"
import "bytes"

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

Tôi nhận được lỗi sau đây:

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)

Tôi bối rối, vì nó thực hiện rõ ràng giao diện. Làm cách nào để giải quyết lỗi này?


2
Tôi đã gặp sự cố này ít nhất hai lần và việc tìm kiếm giải pháp trên Google thực sự không hữu ích.
Kevin Burke

11
Lưu ý rằng việc tạo bufio là không cần thiết. Sử dụng chỉ & b là một io.Writer
Vivien

Câu trả lời:


153

Chuyển một con trỏ đến bộ đệm, thay vì chính bộ đệm:

import "bufio"
import "bytes"

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

4
Tôi tình cờ gặp điều này và muốn tìm hiểu lý do tại sao lại như vậy. Tôi khá lạ lẫm với các con trỏ trong cờ vây.
giờ quay lại

1
Cảm ơn Kevin, lỗi đơn giản này đã mất một giờ đồng hồ của tôi cho đến khi tôi tìm kiếm lỗi này. :)
Nelo Mitranim

7
@hourback nó liên quan đến cách giao diện được triển khai. Thực ra có nhiều cách để triển khai giao diện trong Go. Với máy thu giá trị hoặc con trỏ. Tôi nghĩ đây là một bước ngoặt thực sự đặc biệt của cờ vây. Nếu giao diện được triển khai bằng cách sử dụng bộ thu giá trị theo cả hai cách thì được nhưng nếu giao diện được triển khai bằng bộ thu con trỏ, bạn phải chuyển một con trỏ đến giá trị nếu bạn định sử dụng giao diện. Nó có ý nghĩa vì người viết phải thay đổi bộ đệm để theo dõi vị trí của người viết.
John Leidegren

23
package main

import "bytes"
import "io"

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

Bạn không cần sử dụng "bufio.NewWriter (& b)" để tạo io.Writer. & b chính là io.Writer.


Đây phải là câu trả lời đúng. Nếu bạn cố gắng tạo một trình ghi mới ngoài bộ đệm, bạn sẽ không thể tìm nạp trực tiếp các Byte bộ đệm, điều này làm cho mọi thứ trở nên phức tạp hơn nhiều.
onetwopunch

8

Chỉ dùng

foo := bufio.NewWriter(&b)

Bởi vì cách byte.Buffer triển khai io.Writer là

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, không phải b Buffer. (Tôi cũng nghĩ thật kỳ lạ khi chúng ta có thể gọi một phương thức bằng một biến hoặc con trỏ của nó, nhưng chúng ta không thể gán một con trỏ cho một biến kiểu không phải là con trỏ.)

Bên cạnh đó, lời nhắc trình biên dịch không đủ rõ ràng:

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


Một số ý tưởng, Hãy sử dụng Passed by value, nếu chúng ta chuyển bđến buffio.NewWriter(), trong NewWriter (), nó là một bbộ đệm mới (một bộ đệm mới), không phải bộ đệm ban đầu mà chúng ta đã xác định, do đó chúng ta cần chuyển địa chỉ &b.

Nối lại, byte.Buffer được định nghĩa:

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

bằng cách sử dụng passed by value, cấu trúc bộ đệm mới được truyền vào khác với biến bộ đệm gốc.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.