Example: io.ReadFull
io.ReadFull 用于从 io.Reader 中精确读取指定长度(len(buf))的数据,确保缓冲区被完全填满。
与普通的 io.Read 不同,io.ReadFull 不会因为单次读取数据不足而提前返回成功。它会持续读取,直到满足以下条件之一:
- 成功:读取到了指定长度(即
len(buf))的数据。 - 失败:在缓冲区填满之前,底层 Reader 返回了错误,此时会返回已读取的字节数以及对应错误(如
io.ErrUnexpectedEOF、io.EOF或其他 I/O 错误)。
典型应用场景
- 二进制协议解析(如读取固定长度的 Header)
- 网络数据包拆包(按固定长度读取消息头,避免读取到半包数据)
- 文件头/元数据读取
- 固定大小消息处理
简明示例
最简单的场景:从数据源中精确读取 5 个字节。
Output:
核心价值
普通
reader.Read(buf)并不保证一次读取填满整个缓冲区:
- 可能返回
n == 2,也可能返回n == 4。- 调用方必须自己写循环判断是否读够了所需字节。
而
io.ReadFull(reader, buf)的接口约定:只要返回err == nil,就绝对保证buf已经被全部填满(即读取了len(buf)字节)。
解析固定长度协议头
在二进制协议中,通常会在消息开始位置定义固定大小 Header。
例如:
解析该协议时,必须先完整读取 8 字节的 Header,否则无法获知后续 Payload 的长度。
Output:
边界处理:数据不足时的错误机制
如果底层数据源的数据量少于预期的缓冲区长度,io.ReadFull直接返回错误:
返回:
输出中的
unexpected EOF即io.ErrUnexpectedEOF,表示 Reader 在满足读取长度之前已经结束。
这与io.EOF 不同: