os.readfile适合读取几kb到几mb的小文件(如配置文件),但不可在高频循环中使用;超10mb应流式读取;大文件推荐bufio.scanner(默认64kb缓冲)或bufio.reader。

用 ioutil.ReadFile 最快读小文件,但别在循环里用
读取整个文件到内存,ioutil.ReadFile(Go 1.16+ 已移至 os.ReadFile)最直接。它适合配置文件、JSON、YAML 这类几 KB 到几 MB 的内容。
常见错误是把它塞进高频循环里——比如逐行处理日志时反复调用,会触发大量系统调用和内存分配,性能断崖式下跌。
- Go 1.16+ 请用
os.ReadFile,不是ioutil.ReadFile(后者已弃用) - 文件超过 10MB 就该考虑流式读取,避免 OOM
- 返回的
[]byte是新分配的,原文件修改不影响已读内容
示例:
b, err := os.ReadFile("config.json")
if err != nil {
log.Fatal(err)
}
var cfg Config
json.Unmarshal(b, &cfg)
大文件必须用 bufio.Scanner 或 bufio.Reader
想按行处理 GB 级日志、CSV 或文本流?bufio.Scanner 是默认首选,简洁且自带换行切分逻辑;但它的默认缓冲区只有 64KB,超长行会直接报 scanner.ErrTooLong。
如果行很长、或需要精确控制读取节奏(比如跳过前 N 字节、读固定长度块),就得换 bufio.Reader。
-
Scanner不适合二进制文件或含 的内容 - 调用
Scan()前务必检查Err(),否则可能静默丢掉最后错误 - 用
Scanner.Buffer手动扩容缓冲区,比如s.Buffer(make([]byte, 4096), 1(上限 1MB)
示例(安全读行):
初始化并管理阿里云SDK Go 客户端,涵盖 sync.Once 单例、goroutine 安全、endpoint 与 region 配置、VPC 端点及调试。
file, _ := os.Open("huge.log")
defer file.Close()
s := bufio.NewScanner(file)
for s.Scan() {
line := s.Bytes() // 避免 string(line) 多一次拷贝
process(line)
}
if err := s.Err(); err != nil {
log.Fatal(err)
}
os.Open + io.ReadFull 读固定长度二进制头
解析图片、音频、自定义协议文件时,常需先读前几个字节判断格式(比如 PNG 的 ‰PNG
)。这时候不能靠猜测长度,也不能全读再截取——浪费内存还破坏流式语义。
os.Open 返回 *os.File,配合 io.ReadFull 可精确读满指定字节数,失败时明确区分 “EOF 不足” 和 “其他 I/O 错误”。
-
io.ReadFull返回io.ErrUnexpectedEOF表示文件没那么多字节,不是 panic - 别用
Read自己循环凑长度,容易漏 EOF 或死锁 - 读完记得用
file.Seek(0, io.SeekStart)回到开头,否则后续读取从当前位置开始
示例:
file, _ := os.Open("photo.bin")
defer file.Close()
header := make([]byte, 8)
if _, err := io.ReadFull(file, header); err != nil {
if err == io.ErrUnexpectedEOF {
log.Fatal("file too short for header")
}
log.Fatal(err)
}
if bytes.Equal(header[:4], []byte("‰PNG")) {
// handle PNG
}
Windows 路径和编码问题:别硬写反斜杠,也别假设 UTF-8
Go 的 os 包自动处理路径分隔符,os.Open("dir\sub\file.txt") 在 Linux 会失败,但 os.Open("dir/sub/file.txt") 在所有平台都行——Go 内部会转义。真正麻烦的是中文路径和文件名。
Windows 默认用 GBK/GB2312 编码文件名,而 Go 字符串是 UTF-8。如果用户通过命令行传入含中文的路径,且终端编码非 UTF-8,os.Open 可能直接返回 no such file or directory,错误信息里连路径都显示乱码。
- 开发时统一用英文路径测试,上线前在目标环境实测中文路径
- 避免拼接路径用
+,改用filepath.Join("dir", "file.txt") - 读取文件内容时,编码问题由内容决定(如读 CSV 要看 BOM 或声明),和文件名编码无关
错误示例:os.Open("C:Users张三log.txt") —— 反斜杠被当转义,实际传入的是 C:Userssanlog.txt
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










