不能使用 (type []byte) 作为类型 io.Reader
Cannot use (type []byte) as type io.Reader
我没看懂错误,这是我在本机执行的main.go"A":
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)
}
为什么我会收到错误...
- 不能在 zfs.ReceiveSnapshot 的参数中使用 buff(类型 []byte)作为类型 io.Reader:
[]byte 未实现 io.Reader(缺少 Read 方法)
...当我做 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
.
简短回答:将您的缓冲区包装在 Reader type by using bytes.NewReader
中
或者,您可以使用 bytes.NewBuffer
来达到类似的效果。
如果源是字符串,可以使用strings.NewReader
.
读者名单不断:https://golang.org/search?q=Read#Global
更深层问题的解释
更深层的问题是:为什么数组不直接支持 io.Reader
接口?
io.Reader
支持从通用数据流中读取的概念,不一定事先知道总大小。为了支持这一点,重复调用 Read
直到所有输入数据都用完。在许多语言中,必须至少调用两次类似的读取函数,其中最后一次调用 returns 一个标志,指示 文件结束 .
通过返回两个值(其中一个是 error
类型),Go 可以一次性完成数组读取,但前提是目标缓冲区很大足以消耗所有可用数据——这并不总是事先知道的。
io.Reader
接口指定了 Read()
函数的签名和行为:
func (T) Read(b []byte) (n int, err error)
Read populates the given byte slice with data and returns the number of bytes populated and an error value. It returns an io.EOF error when the stream ends.
因此,由于 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
参数是目标缓冲区,而不是源缓冲区。
我没看懂错误,这是我在本机执行的main.go"A":
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:
的函数 ReceiveSnapshottype 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)
}
为什么我会收到错误...
- 不能在 zfs.ReceiveSnapshot 的参数中使用 buff(类型 []byte)作为类型 io.Reader: []byte 未实现 io.Reader(缺少 Read 方法)
...当我做 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
.
简短回答:将您的缓冲区包装在 Reader type by using bytes.NewReader
或者,您可以使用 bytes.NewBuffer
来达到类似的效果。
如果源是字符串,可以使用strings.NewReader
.
读者名单不断:https://golang.org/search?q=Read#Global
更深层问题的解释
更深层的问题是:为什么数组不直接支持 io.Reader
接口?
io.Reader
支持从通用数据流中读取的概念,不一定事先知道总大小。为了支持这一点,重复调用 Read
直到所有输入数据都用完。在许多语言中,必须至少调用两次类似的读取函数,其中最后一次调用 returns 一个标志,指示 文件结束 .
通过返回两个值(其中一个是 error
类型),Go 可以一次性完成数组读取,但前提是目标缓冲区很大足以消耗所有可用数据——这并不总是事先知道的。
io.Reader
接口指定了 Read()
函数的签名和行为:
func (T) Read(b []byte) (n int, err error)
Read populates the given byte slice with data and returns the number of bytes populated and an error value. It returns an io.EOF error when the stream ends.
因此,由于 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
参数是目标缓冲区,而不是源缓冲区。