简体   繁体   English

不能使用(类型[] byte)作为类型io.Reader

[英]Cannot use (type []byte) as type io.Reader

I don't understand the error, this is my main.go that I execute in the machine "A": 我不明白错误,这是我在机器“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()
}

Now, I show you the function ReceiveSnapshot from github.com/mistifyio/go-zfs/zfs.go: 现在,我向您展示来自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)
}

I have seen in golang pkg the doc of io.Reader: 我在golang pkg中看到了io.Reader的文档:

type Reader interface {
        Read(p []byte) (n int, err error)
}

Why do I receive the error... 为什么我收到错误...

  • cannot use buff (type []byte) as type io.Reader in argument to zfs.ReceiveSnapshot: []byte does not implement io.Reader (missing Read method) 不能使用buff(type [] byte)作为zfs.ReceiveSnapshot参数中的类型io.Reader:[] byte不实现io.Reader(缺少Read方法)

...when I make go install ? ...当我go install

I think you are missing a step in your logic when you think that []byte would be equivalent to Reader just because the Reader's Read method receives a []byte as a parameter. 当你认为[]byteReader等效时,我认为你错过了逻辑中的一步,因为Reader的Read方法接收一个[]byte作为参数。

Let me try to clarify: 让我试着澄清一下:

Your ReceiveSnapshot function expects a Reader as a parameter: 您的ReceiveSnapshot函数需要将Reader作为参数:

ReceiveSnapshot( input io.Reader ...

In order for a type to fulfil the Reader interface, that type should itself implement this function: 为了使类型能够实现Reader接口,该类型本身应该实现此功能:

Read(p []byte) (n int, err error)

Note that the type should implement that function in order to be a Reader . 请注意,该类型应该实现该功能才能成为Reader

[]byte does not implement a Read function. []byte 不实现 Read功能。 It is just a coincidence that the argument to Read happens to be a []byte . 只是巧合, Read的参数恰好是一个[]byte

In order for this to work, you need to send ReceiveSnapshot a proper Reader . 为了使其正常工作,您需要向ReceiveSnapshot发送适当的Reader

Luckily for you, having a []byte and wanting to Read for it is a common situation so the API provides an easy way to do this: 幸运的是,有一个[]byte并想要读取它是一种常见情况,因此API提供了一种简单的方法:

https://golang.org/pkg/bytes/#NewReader https://golang.org/pkg/bytes/#NewReader

You just need to send bytes.NewReader(buff) to your ReceiveSnapshot function instead of just buff . 你只需要将bytes.NewReader(buff)发送到你的ReceiveSnapshot函数而不仅仅是buff

Short answer : Wrap your buffer in a Reader type by using bytes.NewReader 简答 :使用bytes.NewReader将缓冲区包装在Reader类型中

Alternatively, you could use bytes.NewBuffer with similar effect. 或者,您可以使用具有类似效果的bytes.NewBuffer

If the source is a string, you can use strings.NewReader . 如果源是字符串,则可以使用strings.NewReader

The list of Readers goes on and on: https://golang.org/search?q=Read#Global 读者名单一直在继续: https//golang.org/search?q = Read#Global


Explanation of the deeper question 解释更深层次的问题

The deeper question being: Why doesn't an array support the io.Reader interface directly? 更深层次的问题是:为什么数组不直接支持io.Reader接口?

io.Reader supports the concept of reading from a general data stream for which the total size is not necessarily known in advance . io.Reader支持从一般数据流中读取的概念,其总大小不一定是预先知道的 In order to support this, Read is called repeatedly until all input data is exhausted. 为了支持这一点,重复调用Read直到所有输入数据都用完为止。 In many languages, similar read functions must be called at least twice, where the final call returns a flag indicating end-of-file . 在许多语言中,类似的读取函数必须至少调用两次,其中最后的调用返回一个指示文件结尾的标志。

By returning two values (one of which is type error ), Go makes it possible for reading of arrays to complete in one-shot, but only if the destination buffer is large enough to consume all available data -- which isn't always known in advance. 通过返回两个值(其中一个是类型error ),Go可以一次性完成读取数组的读取, 但前提是目标缓冲区足够大以消耗所有可用数据 - 这并不总是已知的提前。

The io.Reader interface specifies the signature and behavior of the Read() function: 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. Read使用数据填充给定的字节片,并返回填充的字节数和错误值。 It returns an io.EOF error when the stream ends. 当流结束时,它返回io.EOF错误。

So due to the way the io.Reader interface works, a simple byte buffer is not capable of implementing it. 因此,由于io.Reader接口的工作方式,一个简单的字节缓冲区无法实现它。 A wrapper structure is required in order to remember the state between subsequent calls to Read() . 需要一个包装器结构,以便记住后续调用Read()之间的状态。

For the sake of interest, here's an example showing how that can be implemented... 为了感兴趣,这里有一个示例说明如何实现...

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

Notice, also, that the []byte parameter to Read() is the destination buffer, not the source. 另请注意, Read()[]byte参数是目标缓冲区,而不是源。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM