贝利信息

如何使用Golang读取日志文件_Golang bufio Scanner日志处理示例

日期:2026-01-01 00:00 / 作者:P粉602998670
bufio.Scanner 读取日志丢行或卡住,主因是默认缓冲区仅64KB且不扩容,超长行(如大JSON)触发“token too long”panic;需调用scanner.Buffer()设足够上限(如10MB),严格检查scanner.Err(),并避免ScanWords等非行切分;遇BOM、多行日志、文件轮转、编码异常等场景应改用bufio.Reader。

为什么 bufio.Scanner 读取日志文件会丢行或卡住

常见现象是程序只读到前几行就退出,或遇到长日志行(比如带超长 JSON 的 access log)直接 panic:scanner: token too long。根本原因是 bufio.Scanner 默认缓冲区只有 64KB,且不自动扩容;它设计目标是安全、流式解析短文本,不是处理任意长度日志行。

如何安全地用 bufio.Scanner 读取生产日志文件

必须重设缓冲区并严格校验错误。下面是最小可行配置:

file, _ := os.Open("/var/log/app.log")
defer file.Close()

scanner := bufio.NewScanner(file)
// 必须在 Scan() 调用前设置
scanner.Buffer(make([]byte, 4096), 10*1024*1024) // 初始 4KB,上限 10MB
scanner.Split(bufio.ScanLines)

for scanner.Scan() {
    line := scanner.Text()
    // 处理单行日志,例如解析时间戳、提取 level
}
if err := scanner.Err(); err != nil {
    // 这里必须处理:可能是 EOF(正常),也可能是 read: connection reset(异常)
    log.Printf("scan error: %v", err)
}

什么时候该放弃 bufio.Scanner 改用 bufio.Reader

当需要精确控制读取行为时——比如跳过 BOM、处理不规范换行、或边读边解压(.log.gz)、或需复用缓冲区做多次 peek ——bufio.Scanner 的封装反而碍事。

真实场景中容易被忽略的三个细节

日志处理不是“打开→读→关”这么简单。以下三点不处理,上线后必出问题: