用os.create+bufio.writer复用1mb缓冲区循环写入,10行代码可控生成gb级测试文件;godu仅查大文件,faker仅适合内存结构体填充,二者均不负责写磁盘。

直接用 os.Create + bufio.Writer 写固定字节块,是生成 GB 级测试文件最稳、最可控的方式。第三方工具如 godu 是查大文件的,不是造大文件的;Faker 库只管结构体字段填充,不负责写磁盘文件。
用 bufio.Write 配合循环写入,10 行代码搞定 1GB 文件
核心思路是复用小缓冲区(如 1MB),避免内存爆炸,同时减少系统调用次数。关键点不在“随机”,而在“可预测大小”和“写入不卡死”。
-
os.Create创建文件后,务必用defer f.Close(),否则文件句柄泄漏 - 缓冲区大小建议设为
1024 * 1024(1MB):太小(如 1KB)会触发大量 write 系统调用;太大(如 100MB)可能吃光内存 - 不要用
fmt.Fprintf或strconv.Itoa拼接字符串再写——它们分配新字符串,对大文件是性能杀手 - 若需内容可读(比如 CSV),用预定义切片拼接二进制数据,例如:
[]byte("login:jbill:2023/01/01, 42\n")
生成带结构的 CSV 测试文件时,别在循环里 new 结构体
你不需要 Faker 库来生成每行数据——它反射开销大,且生成完还得序列化成 CSV 字符串,两步都慢。真要 CSV,就用查表法 + 固定格式写入。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- 把
prefixes、names、dates定义为全局[]string切片,用rand.Intn索引取值 - 时间戳别每次调
time.Now(),改用baseTime.Add(time.Duration(rand.Int63n(365*24*60*60)) * time.Second)随机偏移 - 写入前用
buf := make([]byte, 0, 128)预分配容量,再用buf = append(buf, ...)拼接,避免多次扩容 - 示例片段:
buf = buf[:0] buf = append(buf, prefixes[r.Intn(len(prefixes))]...) buf = append(buf, ':') buf = append(buf, names[r.Intn(len(names))]...) buf = append(buf, ':') buf = append(buf, dateStr...) buf = append(buf, ", "...) buf = append(buf, strconv.AppendInt(buf[:0], int64(r.Intn(1000)), 10)...) buf = append(buf, '\n')
用 godu 查“谁占了空间”,但别指望它生成文件
godu 的定位非常明确:扫描已有目录,按大小排序输出,支持 .goduignore。它没有 --generate 或 -size 参数,源码里也找不到任何文件写入逻辑。
- 执行
godu ~/Downloads可以秒级列出该目录下最大的 20 个文件夹 - 如果误以为它能造大文件,大概率会卡在
godu --help里反复翻找不存在的选项 - 它内部用的是
filepath.WalkDir+os.Stat,纯读操作,零写入
Faker 库只适合构造内存结构体,不适合流式写文件
faker.FakeData(&v) 的本质是反射遍历结构体字段、调用对应 faker 函数、填值。这个过程无法流式对接 io.Writer,更没法控制总字节数。
- 想用 Faker 生成 CSV 行?得先
fake.User{}→ 再fmt.Sprintf→ 再写入,中间多出两次内存拷贝 - 生成百万条记录时,GC 压力陡增,实测比查表法慢 3–5 倍
- 唯一合理用法:生成少量(
真正容易被忽略的点是:文件系统缓存会让首次写入看起来飞快,但关掉 sync 或拔掉 USB 盘再试,你会发现实际落盘速度可能只有 1/10——所以做 I/O 基准测试时,别省略 f.Sync() 和 w.Flush()。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










