[英]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.