interface io.Reader
定义
1 | // go/src/io/io.go |
interface io.Reader
语义
从Reader
中读取数据,存入传入参数p
中,并通过返回值n
返回本次读取的大小,以及err
返回可能存在的错误。
对于一次调用:
可能发生阻塞;不保证读够(读满)len(p)
的数据
n
取值范围0 <= n <= len(p)
- 即使读取到的数据
n < len(p)
,也不保证p
内存块后半部分的原始数据保持不变,不被修改 - 只要有数据可读,即使可读数据
n < len(p)
,也会立即返回,而不是等待读够len(p)
大小的数据
注意,如果没有数据可读并且也没有错误发生,会阻塞当前协程,直到数据可读或发生错误。
(注意,这里说的阻塞指的是上层代码的表现,Go的IO线程协程调度模型不在本文讨论范围内)
正确处理返回值
可能同时出现n > 0
并且err != nil
的情况。
当读取到结尾EOF(end-of-file)时,可以有两种方式
- 首次调用返回
n > 0
并且err != nil
- 首次调用返回
n > 0
并且err == nil
第二次调用返回n == 0
并且err == EOF
第一种方式,即使err != nil
,也有可能读取到了数据。
所以,不管是以上哪种方式,正确处理应该是每次调用结束后,先判断n
,处理读取到的数据,再判断err
,像这样:
1 | n, err := r.Read(p) |
n == 0
并且err == nil
- 正常来说,不应该出现
n == 0
的情况,除非len(p) == 0
- 当
n == 0
并且err == nil
时,应被认为啥事也没发生(一次空调用),而不是EOF
其他
函数调用结束后,内部不会持有p
的内存
interface io.Reader
举例:
1 | // 1. 读取文件 |
本文完,作者yoko,尊重劳动人民成果,转载请注明原文出处: https://pengrl.com/p/20120/