为什么conn.Read()没有在[]字节中写入任何内容,但bufio.Reader.ReadString()有效?

Par*_*dar 2 connection go bufferedreader reader

我有一个连接,像这样创建:

conn, err = net.Dial("tcp", "127.0.0.1:20000")
Run Code Online (Sandbox Code Playgroud)

我尝试过两种方式从这个连接中读取.我认为他们都必须工作,但第一种选择却不行.

这是第一种方式:

var bytes []byte
for i := 0; i < 4; i++ {
    conn.Read(bytes)
}
fmt.Printf("%v", bytes)
Run Code Online (Sandbox Code Playgroud)

此方法的输出是:

[]
Run Code Online (Sandbox Code Playgroud)

这是完全相同的事情,完成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('\n')

    return
}
Run Code Online (Sandbox Code Playgroud)

此函数返回服务器在TCP连接另一端给出的响应.

为什么bufio.Reader.Read()工作,但net.Conn.Read()不是?

icz*_*cza 9

Conn.Read()方法是实现io.Reader,通用接口从任何字节源读取数据到一个[]byte.引用文档Reader.Read():

读取读取最多len(p)个字节到p.

因此,Read()读取最多为len(p)字节但由于您传递了一个nil切片,因此它不会读取任何内容(nil切片的长度为0).请阅读链接的文档以了解其Reader.Read()工作原理.

Reader.Read()不会分配一个缓冲区([]byte)来存储读取数据,你必须创建一个并传递它,例如:

var buf = make([]byte, 100)
n, err := conn.Read(buf)
// n is the number of read bytes; don't forget to check err!
Run Code Online (Sandbox Code Playgroud)

别忘了经常检查返回的error可能是io.EOF如果达到数据结束.的常规协定io.Reader.Read()还允许返回一些非nil错误(包括io.EOF)和一些读取数据(n > 0)在同一时间.读取的字节数将在n,这意味着只有第一个n字节buf是有用的(换句话说:) buf[:n].

你使用的另一个例子bufio.Reader是因为你调用了Reader.ReadString()不需要[]byte参数的.如果您将使用该bufio.Reader.Read()方法,则还必须传递非nil切片以实际获取某些数据.