ioutil.WriteFile 在 Go 1.16+ 已弃用,应改用 os.WriteFile;后者签名一致、无额外依赖,但需注意 data 必须为 []byte、perm 控制新建文件权限、不自动创建父目录且总是覆盖写入。

ioutil.WriteFile 在 Go 1.16+ 已被标记为弃用,直接使用它会触发 deprecated 警告。新项目应改用 os.WriteFile —— 它是 ioutil.WriteFile 的直接替代,签名一致,且无额外依赖。
为什么 ioutil.WriteFile 不该再用了
Go 标准库在 v1.16 将 ioutil 包的功能全部迁入 io 和 os 包。ioutil.WriteFile 被移到 os.WriteFile,并明确标注为 deprecated。继续用它会导致:
- 编译时出现
io/ioutil: deprecated警告(开启-gcflags="-std=off"也压不住) - 静态分析工具(如
staticcheck)报错 - 团队代码规范不通过,尤其在 CI 中启用
go vet或golint时
os.WriteFile 的正确用法和参数含义
os.WriteFile 签名是:func WriteFile(filename string, data []byte, perm fs.FileMode) error。注意三点:
-
data必须是[]byte,不是string—— 即使你想写纯文本,也要显式转成字节切片,例如[]byte("hello\n") -
perm是文件权限(Unix 风格),Windows 上仅控制只读位;常用值如0644(用户可读写,组/其他只读)或0600(仅当前用户可读写) - 它**总是覆盖写入**,不会追加;若需追加,请改用
os.OpenFile+Write
err := os.WriteFile("output.txt", []byte("Hello, Go!\n"), 0644)
if err != nil {
log.Fatal(err)
}
常见错误:中文乱码、换行丢失、权限拒绝
写入文本时出问题,多数不是函数选错,而是编码或路径处理不当:
立即学习“go语言免费学习笔记(深入)”;
- 中文乱码:确保源字符串是 UTF-8 编码(Go 字符串默认就是),但若从其他编码(如 GBK)转换而来,必须先用
golang.org/x/text/encoding转换,否则写入的是非法字节序列 - 换行丢失:Windows 下用
"\r\n",Linux/macOS 用"\n";Go 默认不自动转换,建议统一用"\n"并接受目标系统解释(文本编辑器基本都兼容) - 权限拒绝:传入的
perm值如果含执行位(如0755)且目标目录不可写,或路径中某级目录不存在,os.WriteFile会直接返回no such file or directory错误 —— 它**不会自动创建父目录**
安全写入:避免父目录不存在导致失败
os.WriteFile 不创建中间目录,所以写 "logs/app.log" 前,得先确保 logs/ 存在。可靠做法是:
- 调用
os.MkdirAll(filepath.Dir(filename), 0755)预创建路径 - 注意
0755权限对目录有意义,对文件则可能过于宽松(比如不该有执行位) - 不要忽略
MkdirAll的 error,空目录和只读目录都会让它失败
dir := filepath.Dir("logs/app.log")
if err := os.MkdirAll(dir, 0755); err != nil {
log.Fatal(err)
}
err := os.WriteFile("logs/app.log", []byte("started\n"), 0644)
if err != nil {
log.Fatal(err)
}
最常被忽略的是:os.WriteFile 的 perm 参数只影响新建文件,不影响已存在文件的权限变更;如果文件已存在,它的权限保持不变,内容被覆盖 —— 这点和 shell 的 echo > file 行为一致,但和某些高级 I/O 库不同。










