I don't understand the error, this is my main.go that I execute in the machine "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()
}
Now, I show you the function ReceiveSnapshot from github.com/mistifyio/go-zfs/zfs.go:
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:
type Reader interface {
Read(p []byte) (n int, err error)
}
Why do I receive the error...
...when I make go install
?
The io.Reader interface is used by many packages in the Go standard library and it represents the ability to read a stream of data. More specifically allows you to read data from something that implements the io.Reader interface into a slice of bytes.
The byte type in Golang is an alias for the unsigned integer 8 type ( uint8 ). The byte type is only used to semantically distinguish between an unsigned integer 8 and a byte. The range of a byte is 0 to 255 (same as uint8 ).
Short answer: Wrap your buffer in a Reader type by using bytes.NewReader
Alternatively, you could use bytes.NewBuffer
with similar effect.
If the source is a string, you can use strings.NewReader
.
The list of Readers goes on and on: https://golang.org/search?q=Read#Global
The deeper question being: Why doesn't an array support the io.Reader
interface directly?
io.Reader
supports the concept of reading from a general data stream for which the total size is not necessarily known in advance. In order to support this, Read
is called repeatedly until all input data is exhausted. 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.
The io.Reader
interface specifies the signature and behavior of the Read()
function:
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.
So due to the way the io.Reader
interface works, a simple byte buffer is not capable of implementing it. A wrapper structure is required in order to remember the state between subsequent calls to 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.
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.
Let me try to clarify:
Your ReceiveSnapshot
function expects a Reader
as a parameter:
ReceiveSnapshot( input io.Reader ...
In order for a type to fulfil the Reader
interface, that type should itself implement this function:
Read(p []byte) (n int, err error)
Note that the type should implement that function in order to be a Reader
.
[]byte
does not implement a Read
function. It is just a coincidence that the argument to Read
happens to be a []byte
.
In order for this to work, you need to send ReceiveSnapshot
a proper 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:
https://golang.org/pkg/bytes/#NewReader
You just need to send bytes.NewReader(buff)
to your ReceiveSnapshot
function instead of just buff
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With