os.ReadFile适合读取小于10MB的小文件,自动处理文件打开、读取、关闭,但会全量加载内存,大文件易OOM;逐行读大文件应使用bufio.Scanner,避免手动ReadString导致的边界问题。

用 os.ReadFile 读小文件最简单,但别用它处理大文件
Go 1.16+ 推荐直接用 os.ReadFile,一行搞定,自动处理打开、读取、关闭。但它会把整个文件一次性加载进内存,文件超过几十 MB 就容易 OOM。
- 适合配置文件、JSON、日志片段等小于 10MB 的文本
- 返回
[]byte,需要转字符串用string(data),不是string(*data)(常见笔误) - 错误只返回一个
error,不用自己 deferClose()—— 这是它和os.Open的关键区别
data, err := os.ReadFile("config.txt")
if err != nil {
log.Fatal(err)
}
text := string(data) // ✅ 正确
// text := string(*data) // ❌ data 是切片,不能解引用
逐行读大文件必须用 bufio.Scanner,别手写 ReadString('\n')
bufio.Scanner 是 Go 官方推荐的逐行读取方式,内部做了缓冲和边界处理;手动用 ReadString 容易卡在最后一行没换行符、或被超长行触发 bufio.ErrTooLong。
- 默认单行上限 64KB,读超长日志行会失败,需提前调
scanner.Buffer(make([]byte, 64*1024), 1 - 遇到空行或 EOF 时
scanner.Scan()返回false,别漏判scanner.Err() - 每轮循环里用
scanner.Text()拿当前行,不是scanner.Bytes()(后者生命周期只到下次Scan())
f, _ := os.Open("access.log")
defer f.Close()
scanner := bufio.NewScanner(f)
for scanner.Scan() {
line := scanner.Text() // ✅ 安全持有
process(line)
}
if err := scanner.Err(); err != nil {
log.Fatal(err) // ❌ 别只看 Scan() 结果,漏掉 IO 错误
ioutil.ReadFile 已弃用,升级后必须替换成 os.ReadFile
Go 1.16 起 ioutil 包整体废弃,所有函数移到 io 或 os。继续用 ioutil.ReadFile 会导致构建失败(Go 1.22+ 默认报错),不是警告。
- 替换只需改包名:
io/ioutil→os,函数名不变 - 如果项目还依赖旧版第三方库间接引用
ioutil,得升级那个库,或加//go:build !go1.22条件编译(不推荐) - 别试图 alias:
var ReadFile = ioutil.ReadFile—— 运行时仍会触发弃用提示
中文乱码?先确认文件编码,Go 原生只认 UTF-8
Go 标准库所有字符串和 I/O 操作都假设输入是 UTF-8。如果文件是 GBK、UTF-16 或带 BOM 的 UTF-8,os.ReadFile 读出来就是错的字节序列,转 string 后显示为 或乱码。
立即学习“go语言免费学习笔记(深入)”;
- 用
filetype或chardet类库先探测编码(如github.com/go-enry/go-enry/v2的DetectEncoding) - 转换用
golang.org/x/text/encoding,例如 GBK → UTF-8:decoder := simplifiedchinese.GBK.NewDecoder(); s, _ := decoder.String(string(data)) - 别用
strings.ToValidUTF8魔改 —— 它只是删非法码点,不解决编码识别问题










