如何使用Golang读取日志文件_Golang bufio Scanner日志处理示例
技术百科
P粉602998670
发布时间:2026-01-01
浏览: 次 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.MaxScanTokenSize(65536 字节),超出即报错 - 遇到空行、
\r\n混用、BOM 头时,Scan()可能提前终止迭代 - 未显式检查
Err()就跳出循环,会忽略 I/O 错误(如文件被轮转、权限变化)
如何安全地用 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)
}
-
scanner.Buffer()第二个参数是硬上限,设太小会 panic,设太大浪费内存;10MB 覆盖绝大多数日志行(含嵌套 JSON) - 避免用
bufio.ScanWords或自定义 split,日志行边界就是换行符,用bufio.ScanLines最稳 - 不要在循环内调用
scanner.Bytes()后再scanner.Text(),两者返回的底层切片可能失效
什么时候该放弃 bufio.Scanner 改用 bufio.Reader
当需要精确控制读取行为时——比如跳过 BOM、处理不规范换行、或边读边解压(.log.gz)、或需复用缓冲区做多次 peek ——bufio.Scanner 的封装反而碍事。
- 日志文件由其他进程实时追加,且你需检测文件是否被
logrotate重命名:这时得用os.Stat()对比 inode,Scanner无法感知 - 要支持从指定偏移量恢复读取(断点续读),
Reader.ReadSlice('\n')比更可控
Scanner - 日志行含二进制垃圾数据(如截断的 protobuf),
Scanner遇到非法 UTF-8 会静默失败,而Reader可配合bytes.IndexByte()手动找换行符
真实场景中容易被忽略的三个细节
日志处理不是“打开→读→关”这么简单。以下三点不处理,上线后必出问题:
- 文件可能被
logrotaterename 或 delete,os.Open()成功不代表后续Read()一定成功;需监听inotify或定期os.Stat() - 多行日志(如 Java 异常堆栈)不会自动合并,
Scanner每次只吐一行,需自己缓存并判断是否属于上一条(例如匹配^\t+at或^Caused by:) - 时区与编码:Linux 系统日志默认是本地时区 +
UTF-8,但某些嵌入式设备日志可能是ISO-8859-1,scanner.Text()不做编码转换,乱码只能靠上游统一
# app
# word
# linux
# js
# json
# go
# golang
# java
# 编码
# 字节
# access
# 栈
# node
# 解压
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- Win11怎么查看激活状态_查询Windows 1
- c# Task.ConfigureAwait(tr
- 如何在 VS Code 中正确配置并使用 NumP
- Win11怎么关闭小组件_Win11禁用任务栏天气
- c++ namespace命名空间用法_c++避免
- Win10怎么卸载迅雷_Win10彻底卸载迅雷方法
- c++如何获取map中所有的键_C++遍历键值对提
- Windows电脑键盘突然失灵怎么办?(驱动与硬件
- 如何关闭Win10自动更新更新_Win10系统自动
- Mac电脑进水了怎么办_MacBook进水后紧急处
- Win11怎么关闭透明效果_Windows11辅助
- Win10怎样清理C盘浏览器缓存_Win10清理浏
- Win11怎么设置系统还原_Windows11系统
- 如何在Golang中使用replace替换模块_指
- Python装饰器复用技巧_通用能力解析【教程】
- php查询数据怎么分组_groupby分组查询配合
- PHP 中如何在函数内持久化修改引用变量的指向
- Win10如何备份驱动程序_Win10驱动备份步骤
- 如何解决同一段404代码在不同主机上表现不一致的问
- mac怎么安装pip_MAC Python pip
- 如何在Golang中使用内置函数_Golangle
- php8.4匿名类怎么用_php8.4匿名类创建与
- Win11任务栏怎么放到顶部_Win11修改任务栏
- Win10如何卸载预装Edge扩展_Win10卸载
- Win11笔记本怎么看电池健康度_Win11电池报
- Golang如何遍历目录文件_Golang fil
- C++ STL算法库怎么用?C++常用算法函数(s
- Win11怎样安装搜狗输入法_Win11安装搜狗输
- Windows10系统怎么查看CPU核心数_Win
- php删除数据怎么清空表_truncate与del
- Windows 11怎么更改锁屏超时时间_Wind
- Win10如何备份注册表_Win10注册表备份步骤
- 如何在Golang中实现邮件发送功能_Golang
- c++中如何使用虚函数实现多态_c++多态性实现原
- C++如何将C风格字符串(char*)转换为std
- 如何使用Golang理解结构体指针方法接收者_Go
- c++中的std::conjunction和std
- 如何诊断并终止卡死的 multiprocessin
- Win10如何卸载Skype_Win10卸载Sky
- Win11怎么快速锁屏_Win11一键锁屏快捷键W
- Python数据挖掘进阶教程_分类回归与聚类案例解
- Python如何创建带属性的XML节点
- Win11怎么设置环境变量_Win11配置Path
- php本地部署支持nodejs吗_php与node
- Windows10如何更改盘符名称_Win10重命
- Win11怎么退出高对比度模式_Win11取消反色
- mac怎么右键_MAC鼠标右键设置与触控板手势技巧
- LINUX怎么设置系统语言_LINUX修改中文环境
- Python异步网络编程_aiohttp说明【指导
- PyTorch DDP 多进程训练在 Kaggle

Scanner
QQ客服