之前学习go的时候被这个ReadLine
坑了一段时间,以为加个for循环就会一行一行的读下去。当时好像调试了半天之类的,总之今天来带你们看看他怎么实现的吧。
首先我们构造一个Reader方便我们调试与分析:
sr := strings.NewReader("123\n456");
reader := bufio.NewReader(sr);
line, _, err := reader.ReadLine();
if err != nil {
panic(err)
}
fmt.Println(string(line))
输出:123
这个时候你也大致明白这个函数的内部原理了吧。他会读取\n
之前的数据也就是”123”返回给我们。
ReadLine的源码分析:
以下完全是个人理解如果有错误那就再下面评论吧。
line, err = b.ReadSlice('\n')
首先从第一行代码开始同是最重要的一行代码,这行代码是以\n
为结束符读取数据。
if err == ErrBufferFull {
// Handle the case where "\r\n" straddles the buffer.
if len(line) > 0 && line[len(line)-1] == '\r' {
// Put the '\r' back on buf and drop it from line.
// Let the next call to ReadLine check for "\r\n".
if b.r == 0 {
// should be unreachable
panic("bufio: tried to rewind past start of buffer")
}
b.r--
line = line[:len(line)-1]
}
return line, true, nil
}
这个ErrBufferFull 暂时不知道从哪里返回的,等以后发现了会修改。
if len(line) == 0 {
if err != nil {
line = nil
}
return
}
这几行代码主要是做一个为空判断,很容易理解。
if line[len(line)-1] == '\n' {
drop := 1
if len(line) > 1 && line[len(line)-2] == '\r' {
drop = 2
}
line = line[:len(line)-drop]
}
这几行代码是处理line最后两位数据有\n \r
- 数据的最后一位为
'\n'
- 如果
line
长度大于1并且倒数第二位为'\r'
截取长度+1- 截取数组