golang 从 io.Reader 读取数据
io.Reader
1
2
3
|
type Reader interface {
Read(p []byte) (n int, err error)
}
|
Reader接口用于包装基本的读取方法。
Read方法读取len(p)字节数据写入p。它返回写入的字节数和遇到的任何错误。即使Read方法返回值n < len(p),本方法在被调用时仍可能使用p的全部长度作为暂存空间。如果有部分可用数据,但不够len(p)字节,Read按惯例会返回可以读取到的数据,而不是等待更多数据。
当Read在读取n > 0个字节后遭遇错误或者到达文件结尾时,会返回读取的字节数。它可能会在该次调用返回一个非nil的错误,或者在下一次调用时返回0和该错误。一个常见的例子,Reader接口会在输入流的结尾返回非0的字节数,返回值err == EOF或err == nil。但不管怎样,下一次Read调用必然返回(0, EOF)。调用者应该总是先处理读取的n > 0字节再处理错误值。这么做可以正确的处理发生在读取部分数据后的I/O错误,也能正确处理EOF事件。
如果Read的某个实现返回0字节数和nil错误值,表示被阻碍;调用者应该将这种情况视为未进行操作。
以 net.Conn
中读取数据为例
使用TCP连接访问某个网站,采用HTTP 1.0的协议,让TCP连接保持短连接,读取完response之后连接会关闭,这样就模拟了io.EOF的错误
1
2
3
4
5
6
7
8
|
conn, err := net.Dial("tcp", "rpcx.site:80")
if err != nil {
fmt.Println("dial error:", err)
return
}
defer conn.Close()
// 发送请求, http 1.0 协议
fmt.Fprintf(conn, "GET / HTTP/1.0\r\n\r\n")
|
io.Reader.Read
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
// 读取response
var sb strings.Builder
buf := make([]byte, 256)
for {
n, err := conn.Read(buf)
if err != nil {
if err != io.EOF {
fmt.Println("read error:", err)
}
break
}
sb.Write(buf[:n])
}
// 显示结果
fmt.Println("response:", sb.String())
fmt.Println("total response size:", sb.Len())
|
io.Copy
1
2
3
4
5
6
7
8
9
|
// 读取response
var sb strings.Builder
_, err = io.Copy(&sb, conn)
if err != nil {
fmt.Println("read error:", err)
}
// 显示结果
fmt.Println("response:", sb.String())
fmt.Println("total response size:", sb.Len())
|
ioutil.ReadAll
1
2
3
4
5
6
7
8
9
10
11
|
// 读取response
data, err := ioutil.ReadAll(conn)
if err != nil {
if err != io.EOF {
fmt.Println("read error:", err)
}
panic(err)
}
// 显示结果
fmt.Println("response:", string(data))
fmt.Println("total response size:", len(data))
|
io.ReadFull
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
// 读取response
var sb strings.Builder
buf := make([]byte, 256)
for {
n, err := io.ReadFull(conn, buf)
if err != nil {
if err != io.EOF && err != io.ErrUnexpectedEOF {
fmt.Println("read error:", err)
}
break
}
sb.Write(buf[:n])
}
// 显示结果
fmt.Println("response:", sb.String())
fmt.Println("total response size:", sb.Len())
|
io.ReadAtLeast
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
// 读取response
var sb strings.Builder
buf := make([]byte, 379)
for {
n, err := io.ReadAtLeast(conn, buf, 379)
if err != nil {
if err != io.EOF && err != io.ErrUnexpectedEOF {
fmt.Println("read error:", err)
}
break
}
sb.Write(buf[:n])
}
// 显示结果
fmt.Println("response:", sb.String())
fmt.Println("total response size:", sb.Len())
|
io.LimitReader
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
// 读取response
var sb strings.Builder
buf := make([]byte, 379)
rr := io.LimitReader(conn, 102400)
for {
n, err := io.ReadAtLeast(rr, buf, 379)
if err != nil {
if err != io.EOF && err != io.ErrUnexpectedEOF {
fmt.Println("read error:", err)
}
break
}
sb.Write(buf[:n])
}
// 显示结果
fmt.Println("response:", sb.String())
fmt.Println("total response size:", sb.Len())
|
bufio.Read
1
2
3
4
5
6
7
8
9
10
11
12
13
|
// 读取response
reader := bufio.NewReader(conn)
buf := make([]byte, 379)
n, err := reader.Read(buf)
if err != nil {
if err != io.EOF {
fmt.Println("read error:", err)
}
panic(err)
}
// 显示结果
fmt.Println("response:", string(buf[:n]))
fmt.Println("total response size:", len(buf[:n]))
|
参考