I have a connection, created like this:
conn, err = net.Dial("tcp", "127.0.0.1:20000")
I have tried reading from this connection in two ways. I think they both must work, but the first option doesn't.
Here is the first way of doing it:
var bytes []byte
for i := 0; i < 4; i++ {
conn.Read(bytes)
}
fmt.Printf("%v", bytes)
The output of this method is:
[]
And here is the same thing, done with bufio.Reader
:
func readResponse(conn net.Conn) (response string, err error) {
reader := bufio.NewReader(conn)
_, err = reader.Discard(8)
if err != nil {
return
}
response, err = reader.ReadString('
')
return
}
This function returns the response given by the server on the other end of the TCP connection.
Why does bufio.Reader.Read()
work, but net.Conn.Read()
doesn't?
The Conn.Read()
method is to implement io.Reader
, the general interface to read data from any source of bytes into a []byte
. Quoting from the doc of Reader.Read()
:
Read reads up to len(p) bytes into p.
So Read()
reads up to len(p)
bytes but since you pass a nil
slice, it won't read anything (length of a nil
slice is 0
). Please read the linked doc to know how Reader.Read()
works.
Reader.Read()
does not allocate a buffer ([]byte
) where the read data will be stored, you have to create one and pass it, e.g.:
var buf = make([]byte, 100)
n, err := conn.Read(buf)
// n is the number of read bytes; don't forget to check err!
Don't forget to always check the returned error
which may be io.EOF
if end of data is reached. The general contract of io.Reader.Read()
also allows returning some non-nil
error (including io.EOF
) and some read data (n > 0
) at the same time. The number of read bytes will be in n
, which means only the first n
bytes of the buf
is useful (in other words: buf[:n]
).
Your other example using bufio.Reader
works because you called Reader.ReadString()
which doesn't require a []byte
argument. If you would've used the bufio.Reader.Read()
method, you would also had to pass a non-nil
slice in order to actually get some data.