英文:
Why does conn.Read() write nothing into a []byte, but bufio.Reader.ReadString() works?
问题
我有一个连接,创建方式如下:
conn, err = net.Dial("tcp", "127.0.0.1:20000")
我尝试了两种方式从这个连接中读取数据。我认为它们都应该有效,但第一种方式不行。
以下是第一种方式:
var bytes []byte
for i := 0; i < 4; i++ {
conn.Read(bytes)
}
fmt.Printf("%v", bytes)
这种方法的输出是:
[]
以下是使用 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
}
这个函数返回与 TCP 连接的另一端的服务器返回的响应。
为什么 bufio.Reader.Read()
起作用,而 net.Conn.Read()
不起作用呢?
英文:
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('\n')
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?
答案1
得分: 12
Conn.Read()
方法是实现 io.Reader
接口的,该接口用于从任何字节源读取数据到 []byte
中。引用自 Reader.Read()
的文档:
> 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 是读取的字节数;不要忘记检查 err!
不要忘记始终检查返回的 error
,如果达到数据末尾,可能会返回 io.EOF
。io.Reader.Read()
的一般约定还允许同时返回一些非 nil
的错误(包括 io.EOF
)和一些读取的数据(n > 0
)。读取的字节数将在 n
中,这意味着只有 buf
的前 n
个字节是有用的(换句话说:buf[:n]
)。
你的另一个使用 bufio.Reader
的示例有效,因为你调用了 Reader.ReadString()
,它不需要一个 []byte
参数。如果你使用了 bufio.Reader.Read()
方法,你也必须传递一个非 nil
的切片才能实际获取一些数据。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论