![](/img/trans.png)
[英]Buffer issue cannot use <type> as type io.Reader in argument to http.NewRequest golang
[英]Cannot use (type []byte) as type io.Reader
我不明白錯誤,這是我在機器“A”中執行的main.go:
package main
import (
"fmt"
"net"
"os"
"github.com/mistifyio/go-zfs"
)
func main() {
// Listen for incoming connections.
l, err := net.Listen("tcp", "192.168.99.5:9977")
if err != nil ...
// Close the listener when the application closes.
defer l.Close()
fmt.Println("Listening on " + CONN_HOST + ":" + CONN_PORT)
for {
// Listen for an incoming connection.
conn, err := l.Accept()
if err != nil ...
//Handle connections in a new goroutine.
go handleRequest(conn)
}
}
// Handles incoming requests.
func handleRequest(conn net.Conn) {
// Make a buffer to hold incoming data.
buff := make([]byte, 1024)
// Read the incoming connection into the buffer.
_, err := conn.Read(buff)
if err != nil {
fmt.Printf("Error reading: %s.\n", err.Error())
}
// ReceiveSnapshot
ds, err := zfs.ReceiveSnapshot(buff, "tank/replication")
if err != nil {
fmt.Printf("Error receiving: %s.\n", err.Error())
}
fmt.Printf("%s... done!\n", ds)
// Send a response back to person contacting us.
conn.Write([]byte("Received!"))
// Close the connection when you're done with it.
conn.Close()
}
現在,我向您展示來自github.com/mistifyio/go-zfs/zfs.go的函數ReceiveSnapshot:
type command struct {
Command string
Stdin io.Reader
Stdout io.Writer
}
func ReceiveSnapshot(input io.Reader, name string) (*Dataset, error) {
c := command{Command: "zfs", Stdin: input}
_, err := c.Run("receive", name)
if err != nil {
return nil, err
}
return GetDataset(name)
}
我在golang pkg中看到了io.Reader的文檔:
type Reader interface {
Read(p []byte) (n int, err error)
}
為什么我收到錯誤...
...當我go install
?
當你認為[]byte
與Reader
等效時,我認為你錯過了邏輯中的一步,因為Reader的Read
方法接收一個[]byte
作為參數。
讓我試着澄清一下:
您的ReceiveSnapshot
函數需要將Reader
作為參數:
ReceiveSnapshot( input io.Reader ...
為了使類型能夠實現Reader
接口,該類型本身應該實現此功能:
Read(p []byte) (n int, err error)
請注意,該類型應該實現該功能才能成為Reader
。
[]byte
不實現 Read
功能。 只是巧合, Read
的參數恰好是一個[]byte
。
為了使其正常工作,您需要向ReceiveSnapshot
發送適當的Reader
。
幸運的是,有一個[]byte
並想要讀取它是一種常見情況,因此API提供了一種簡單的方法:
https://golang.org/pkg/bytes/#NewReader
你只需要將bytes.NewReader(buff)
發送到你的ReceiveSnapshot
函數而不僅僅是buff
。
簡答 :使用bytes.NewReader
將緩沖區包裝在Reader類型中
或者,您可以使用具有類似效果的bytes.NewBuffer
。
如果源是字符串,則可以使用strings.NewReader
。
讀者名單一直在繼續: https : //golang.org/search?q = Read#Global
更深層次的問題是:為什么數組不直接支持io.Reader
接口?
io.Reader
支持從一般數據流中讀取的概念,其總大小不一定是預先知道的 。 為了支持這一點,重復調用Read
直到所有輸入數據都用完為止。 在許多語言中,類似的讀取函數必須至少調用兩次,其中最后的調用返回一個指示文件結尾的標志。
通過返回兩個值(其中一個是類型error
),Go可以一次性完成讀取數組的讀取, 但前提是目標緩沖區足夠大以消耗所有可用數據 - 這並不總是已知的提前。
io.Reader
接口指定Read()
函數的簽名和行為:
func (T) Read(b []byte) (n int, err error)
Read使用數據填充給定的字節片,並返回填充的字節數和錯誤值。 當流結束時,它返回io.EOF錯誤。
因此,由於io.Reader
接口的工作方式,一個簡單的字節緩沖區無法實現它。 需要一個包裝器結構,以便記住后續調用Read()
之間的狀態。
為了感興趣,這里有一個示例說明如何實現...
type MyReader struct {
src []byte
pos int
}
func (r *MyReader) Read(dst []byte) (n int, err error) {
n = copy(dst, r.src[r.pos:])
r.pos += n
if r.pos == len(r.src) {
return n, io.EOF
}
return
}
func NewMyReader(b []byte) *MyReader { return &MyReader{b, 0} }
另請注意, Read()
的[]byte
參數是目標緩沖區,而不是源。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.