带缓冲的读取器
使用 bufio 高效读取
带缓冲的读取器 是 CoddyKit 上的免费 Go Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Go Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Go Academy 课程共包含 4 节课。
为什么要进行 Buffer 读取
从文件或网络一次读取一个字节,每次都会触发系统调用。这样很慢。
bufio 包装读取器,将数据分块读入内存中的缓冲区,再从该缓冲区为您的小量读取提供数据。
- 系统调用更少
- 处理大量小量读取时快得多
创建 bufio.Reader
使用 bufio.NewReader 包装任何 io.Reader。这里我们包装一个 strings.Reader。
package main
import (
"bufio"
"fmt"
"strings"
)
func main() {
r := bufio.NewReader(strings.NewReader("Hello, Go!"))
fmt.Printf("buffered reader ready: %T\n", r)
}读取 Bytes
ReadByte 返回下一个字节。该字节来自缓冲区,而不是通过新的系统调用读取。
package main
import (
"bufio"
"fmt"
"strings"
)
func main() {
r := bufio.NewReader(strings.NewReader("Go"))
b1, _ := r.ReadByte()
b2, _ := r.ReadByte()
fmt.Printf("%c%c\n", b1, b2)
}使用 ReadString 读取到分隔符
ReadString(delim) 读取数据,直到遇到分隔符字节的第一次出现,并返回包括分隔符在内的全部内容。
package main
import (
"bufio"
"fmt"
"strings"
)
func main() {
r := bufio.NewReader(strings.NewReader("first,second,third"))
part, _ := r.ReadString(',')
fmt.Printf("%q\n", part)
}预读后续内容
Peek(n) 返回接下来的 n 个字节,但不会消耗它们。在确定解析方式之前进行判断时非常有用。
package main
import (
"bufio"
"fmt"
"strings"
)
func main() {
r := bufio.NewReader(strings.NewReader("HTTP/1.1"))
head, _ := r.Peek(4)
fmt.Printf("starts with: %s\n", head)
}Buffer 大小
bufio.NewReaderSize(r, size) 设置缓冲区容量。缓冲区越大,底层读取次数越少,但占用的内存越多。
package main
import (
"bufio"
"fmt"
"strings"
)
func main() {
r := bufio.NewReaderSize(strings.NewReader("data"), 4096)
fmt.Println("buffer size:", r.Size())
}ReadLine 与 ReadString
ReadString('\n') 会保留换行符;许多解析器更喜欢将其去除。Scanner 会自动处理这一点(下一课介绍)。
当您需要完全控制分隔符时,请使用 ReadString。
处理 io.EOF
底层流耗尽时,读取方法会返回 io.EOF。请始终检查它,以确定何时停止。
package main
import (
"bufio"
"fmt"
"io"
"strings"
)
func main() {
r := bufio.NewReader(strings.NewReader("ab"))
for {
c, err := r.ReadByte()
if err == io.EOF {
break
}
fmt.Printf("%c", c)
}
fmt.Println()
}使用 ReadRune 读取 Unicode
ReadRune 会解码完整的 UTF-8 符文,而一个符文可能跨越多个字节。对于包含非 ASCII 字符的文本,请使用它。
package main
import (
"bufio"
"fmt"
"strings"
)
func main() {
r := bufio.NewReader(strings.NewReader("héllo"))
for {
ru, _, err := r.ReadRune()
if err != nil {
break
}
fmt.Printf("%c ", ru)
}
fmt.Println()
}读取直到完成
一种常见模式是:使用 ReadString 循环读取直到 EOF,从而逐行处理流,同时保持精细的控制。
package main
import (
"bufio"
"fmt"
"io"
"strings"
)
func main() {
r := bufio.NewReader(strings.NewReader("a\nb\nc\n"))
for {
line, err := r.ReadString('\n')
fmt.Print("got: " + line)
if err == io.EOF {
break
}
}
}何时使用 bufio.Reader
- 包装较慢的数据源(文件、套接字)
- 需要进行大量小量读取时
- 需要预读,或按分隔符/符文读取时
对于简单的逐行扫描,请优先使用 bufio.Scanner(下一课介绍)。
快速检查
测试您对带缓冲读取器的理解。
回顾
您已经学会了 bufio.Reader 如何通过缓冲减少系统调用。
NewReader/NewReaderSize包装一个 io.ReaderReadByte、ReadRune、ReadString从缓冲区提供数据Peek可以预读而不消耗数据- 遇到
io.EOF时停止
用 AI 导师学习 Go — 免费
在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。
- 课程
- 51
- 课程
- 203
常见问题解答
「带缓冲的读取器」课时是免费的吗?
是的 — 「带缓冲的读取器」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Go Academy 课程的其余内容,请升级到 CoddyKit PRO。 Go Academy 课程共包含 4 节课。
「带缓冲的读取器」这节课中我会学到什么?
使用 bufio 高效读取 你通过在浏览器中直接运行的动手代码来练习 Go Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Go Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Go Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。
「带缓冲的读取器」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Go Academy 课中编写并运行代码吗?
能。每节 Go Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。