bufio/#Reader.Peek疑问

来源:15-6 测试CityListParser

kxning

2018-03-24

在14-6节中,因为Peek导致读取的内容不全,通过bufio.NewReader包装resp.Body后,再读取就正常了。

我看了Peek实现(https://golang.org/src/bufio/bufio.go),只是截取了指定长度n的字节,并没有移动reader的位置指针,有下面2个疑问:

为什么Peek后会导致后面再读取的数据没有Peek的内容呢?

NewReader包装后为什么就可以?

不理解这里,麻烦老师指导下,谢谢。



写回答

3回答

乐只君子

2019-06-01

这个问题比较边缘,也看了很久

补充一个注意点,bufio.NewReader 的默认 buf 大小是 4096

也就是说如果 Peek 的 size 大于 4096 的话,还是有问题的

这时需要使用 bufio.NewReaderSize

1
0

ccmouse

2018-09-08

首先从逻辑上理解:io.Reader的Read本身就必须伴随着指针的移动,不然我反复调这个io.Reader的Read都获得相同的内容,显然不对。

那么io.Reader是没有Peek能力的,我(bufio.Reader)为了看1024字节的内容,只有一个办法,把他们读进buffer,然后告诉外面假装我Peek到了哪些内容。而这个原始的io.Reader被读了1024字节后,下一个Read只能从1025字节开始读。

代码上,bufio.go的132行调用了fill,fill里面显然调用了原始的这个io.Reader的Read方法。


0
0

kxning

提问者

2018-03-24

描述完问题有了些理解,请看看对不对

a. Peek是针对bufio的

b. 错误的做法 bufio.NewReader(resp.Body).Peek() 将resp.Body的读取指针移动了,然后再读取resp.Body 导致数据少了

c. 正确的做法,先将resp.Body转换bufio.NewReader,再Peek,然后读取bufio.NewReader,所以指针并没有移动,读取的内容是全的

0
3
bbmouse
回复
ccmouse
这个问题看了老师及大家的讨论,我猜应该是这样: bufio.NewReader(resp.Body).Peek() 这句,想要peek到数据,bufio必需读取resp.body的内容,所以这行执行后,resp.body的指针会移动,然后1024数据读到了buffer里,如果外面继续对resp.Body读取,因为指针动了,所以只能从1025开始读,所以要解决这个问题,就是我们应该继续从buffer里读取,里面有已经缓冲了1024的内容,再次从bufio读取,bufio就会把剩下的内容读继续读到buffer里,然后我们从buffer读,内容就是全的,不知道这样理解对不对
2019-07-11
共3条回复

Google资深工程师深度讲解Go语言 由浅入深掌握Go语言

语法+分布式爬虫实战 为转型工程师量身打造

5995 学习 · 1909 问题

查看课程