最近在尝试学习go语言,想去洛谷做几道题吧,结果前几个答案是正确的,最后两个报了超时,标准输入输出fmt存在读写性能上的缺陷。deepseek推荐了这个bufio包。
bufio 包的核心功能
bufio 提供缓冲 I/O,通过减少系统调用来提升读写性能。
| 类型 | 用途 |
|---|---|
bufio.Reader | 带缓冲的读取器 |
bufio.Writer | 带缓冲的写入器 |
bufio.Scanner | 按 token(行/单词等)扫描的便捷工具 |
bufio.ReadWriter | Reader + Writer 的组合 |
Scanner 的默认行为
默认缓冲区大小 = 64KB (bufio.MaxScanTokenSize)
默认分割函数 = ScanLines(按换行符分割)
Buffer 方法
- buf:提供外部缓冲区(避免内部小缓冲区频繁扩容)
- max:允许的最大 token 长度(必须 >= 16 且通常 >= len(buf))
scanner.Buffer(buf []byte, max int)分割逻辑
scanner.Split(bufio.ScanWords) 的作用是改变 Scanner 的分割逻辑,从默认的按行分割改为按单词分割。
| 函数 | 分割规则 | token 示例 |
|---|---|---|
ScanLines (默认) | 按换行符 \n,自动去掉换行 | "第一行", "第二行" |
ScanWords | 按 Unicode 字母数字边界,空格/标点分隔 | "Hello", "world,"(逗号保留) |
ScanRunes | 按 UTF-8 字符分割 | 'H', 'e', '你', '好' |
ScanBytes | 按字节分割 | byte(72), byte(101) |
P1170 兔八哥与猎人实战
仅使用fmt包的情况下,最后的两个测试点会因超时而无法通过。
package main
import (
"bufio"
"fmt"
"os"
"strconv"
)
var scanner *bufio.Scanner
func init() {
scanner = bufio.NewScanner(os.Stdin)
scanner.Buffer(make([]byte, 1024*1024), 1024*1024)
scanner.Split(bufio.ScanWords)
}
func nextInt() int {
scanner.Scan()
num, _ := strconv.Atoi(scanner.Text())
return num
}
func Abs(x int) int {
if x < 0 {
return -x
}
return x
}
func Gcd(x, y int) int {
if y == 0 {
return x
}
return Gcd(y, x%y)
}
func main() {
n := nextInt()
for i := 1; i <= n; i++ {
hx := nextInt()
hy := nextInt()
rx := nextInt()
ry := nextInt()
res := Gcd(Abs(hx-rx), Abs(hy-ry))
if res == 1 {
fmt.Println("no")
} else {
fmt.Println("yes")
}
}
}性能注意事项
| 分割方式 | 性能 | 适用场景 |
|---|---|---|
ScanLines | 最快 | 日志文件、配置文件(每行独立) |
ScanWords | 较快 | 文本分析、词频统计 |
ScanRunes | 中等 | 处理 Unicode 文本、字符级操作 |
ScanBytes | 最快 | 二进制数据处理 |

