应改用os.writefile;它替代已弃用的ioutil.writefile,签名一致、自动处理文件打开/写入/关闭,需传[]byte和权限(如0644),不创建父目录且总是覆盖写入。

用 ioutil.WriteFile 最快写入单次内容
如果只是把一整段字符串一次性存到文件里,ioutil.WriteFile 是最直接的选择。它自动处理文件打开、写入、关闭全过程,不用手动管理资源。
- 注意:Go 1.16+ 中
ioutil已被弃用,应改用os.WriteFile(行为完全一致,只是包路径变了) - 第三个参数是文件权限,Linux/macOS 常用
0644,Windows 可设为0666(实际权限由系统 umask 调整) - 若目标路径含不存在的父目录,会直接报错
no such file or directory,需提前创建
err := os.WriteFile("output.txt", []byte("hello world"), 0644)
if err != nil {
log.Fatal(err)
}
用 os.OpenFile + Write 追加或控制写入行为
当需要追加内容、写入多段数据、或精确控制缓冲/同步行为时,得自己开文件句柄。这时不能只用 os.Create,因为它总 truncates(清空原文件),而 os.OpenFile 更灵活。
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
- 追加模式要传 flag
os.O_APPEND | os.O_CREATE | os.O_WRONLY - 写完不
Close()会导致文件句柄泄漏,尤其在循环中极易触发too many open files -
Write不保证立即落盘,如需强一致性(比如日志关键行),得调用file.Sync()
f, err := os.OpenFile("log.txt", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
log.Fatal(err)
}
defer f.Close()
_, err = f.Write([]byte("new line\n"))
if err != nil {
log.Fatal(err)
}
中文乱码?检查字符串编码和编辑器默认格式
Go 字符串原生是 UTF-8,写入文件后仍是 UTF-8 编码。所谓“乱码”通常不是 Go 的问题,而是查看工具用了错误编码(比如 Windows 记事本默认 ANSI)。
- 用 VS Code、Notepad++ 或
cat查看一般不会出问题 - Windows 上双击用记事本打开 → 选“另存为”,编码下拉框确认是 UTF-8(带 BOM 的 UTF-8 有时更兼容,但 Go 写出的是无 BOM 的标准 UTF-8)
- 不要尝试用
gob或 base64 包装字符串再写——那不是解决乱码,是制造新问题
大文件写入别直接 []byte 转换
把几 MB 甚至更大的字符串转成 []byte 会瞬间复制一份内存副本,可能触发 OOM。真正的大文本应流式处理。
- 用
bufio.NewWriter包裹文件句柄,批量写入、减少系统调用次数 - 避免反复
WriteString小片段;攒够一定长度(比如 4KB)再刷盘 - 如果源数据来自网络或数据库,优先考虑边读边写,而不是先拼成一个巨型字符串
w := bufio.NewWriter(f)
w.WriteString("line 1\n")
w.WriteString("line 2\n")
w.Flush() // 必须显式 flush,否则可能滞留在 buffer 中
文件路径里的相对路径容易被工作目录搞混,os.WriteFile 用的是当前进程启动时的 pwd,不是源码所在目录。真要可靠,就用 filepath.Join(filepath.Dir(runtime.Caller(0).Filename), "data.txt") 拿源码同级路径——但这只适用于二进制运行时,交叉编译或打包后行为可能变化。golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










