为什么conn.Read()不会将任何内容写入[]字节,但是bufio.Reader.ReadString()可以工作?

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.