为何使用bufio.Reader读取流后,第二次读取时流显示为空?
为何使用bufio.Reader读取流后,第二次读取时流显示为空?
嗨,这个问题我刚接触Go的IO操作时也踩过一模一样的坑!
其实核心原因是bufio.Reader的预读优化机制在搞事情:当你用bufio.NewReader(buf)创建读取器,再调用ReadString('\n')的时候,它可不是只读到换行符就收手。为了提升IO效率,这个读取器会一次性从底层的buf流(不管是文件还是其他实现os.Reader的缓冲区)里读取一大块数据,存到自己的内部缓冲区里——哪怕你只需要那一行带换行符的内容。
举个实际的例子:假设你的buf里有2000字节的内容,而你第一次调用ReadString('\n')只需要前80字节(到第一个换行符的位置),但bufio.Reader可能已经把这2000字节全读到自己的内部缓冲区了。这时候底层buf流的读取偏移量已经走到了末尾,你再直接去读buf的话,自然就显示为空、读取大小是0了。
这里还要提醒你一个关键:如果你想继续读取剩下的内容,或者不想让底层流被一次性掏空,千万不要每次都新建bufio.Reader实例。正确的做法是复用同一个bufio.Reader,它会自己管理内部缓冲区里剩下的数据,不会乱移动底层流的偏移量。比如:
// 正确姿势:只创建一次bufio.Reader reader := bufio.NewReader(buf) // 第一次读取行 firstLine, err := reader.ReadString('\n') // 第二次读取,用同一个reader,它会从内部缓冲区取剩下的内容 secondLine, err := reader.ReadString('\n')
另外要注意,像文件这种底层os.Reader实现,它们的读取偏移量是单向前进的,一旦被读过就不会自动重置。bufio.Reader的预读直接把偏移量拉到了流的末尾,这就导致你再直接操作底层buf时,根本没数据可读了。
内容来源于stack exchange
相关产品推荐
相关产品推荐

