Go 1.16+ 必须用 os.CreateTemp 替代已弃用并移除的 ioutil.TempFile;其参数为 dir 和 pattern(需含 ""),返回已打开且权限 0600 的文件,常见错误包括漏写 ""、重复打开及路径构造不当。

ioutil.TempFile 在 Go 1.16+ 已被弃用,直接使用 os.CreateTemp —— 这是当前唯一推荐方式,旧代码升级时必须改。
为什么不能继续用 ioutil.TempFile
Go 1.16 开始,ioutil 包整体被移入 io 和 os,其中 ioutil.TempFile 的功能完全由 os.CreateTemp 承接。继续保留旧导入会触发编译错误:undefined: ioutil.TempFile。
- Go 1.15 及更早:可用,但已标记为 deprecated
- Go 1.16+:
ioutil包不存在,必须切换 - 行为上二者几乎一致,但
os.CreateTemp参数顺序更合理(先 dir 后 pattern)
os.CreateTemp 基本用法与参数含义
签名是 func CreateTemp(dir, pattern string) (f *os.File, err error),关键点在于:
-
dir:临时目录路径,传空字符串""表示使用系统默认(os.TempDir()) -
pattern:文件名模板,必须包含至少一个"*",会被替换成随机字符串(如"myapp-*.log") - 返回的
*os.File已打开(可读写),且权限默认为0600(仅当前用户可读写)
tmpFile, err := os.CreateTemp("", "backup-*.json")
if err != nil {
log.Fatal(err)
}
defer os.Remove(tmpFile.Name()) // 记得清理
defer tmpFile.Close()
_, _ = tmpFile.WriteString(`{"data":"example"}`)
常见错误和兼容性注意点
实际写代码时容易卡在这几个地方:
立即学习“go语言免费学习笔记(深入)”;
网奇Eshop是一个带有国际化语言支持的系统,可以同时在一个页面上显示全球任何一种语言而没有任何障碍、任何乱码。在本系统中您可以发现,后台可以用任意一种语言对前台进行管理、录入而没有阻碍。而任何一个国家的浏览者也可以用他们的本国语言在你的网站上下订单、留言。用户可以通过后台随意设定软件语言,也就是说你可以用本软件开设简体中文、繁体中文与英文或者其他语言的网上商店。网奇Eshop系统全部版本都使用模
- 传错
pattern:漏掉"*"(如"backup.json")→ 报错"pattern contains no asterisk" - 忽略返回的
*os.File已打开 → 重复os.Open导致 “text file busy” 或权限错误 - 在 Windows 上指定
dir时路径末尾带反斜杠但没转义 → 字符串解析失败(建议用filepath.Join构造路径) - 并发调用未加锁 → 虽然
os.CreateTemp内部是线程安全的,但若多个 goroutine 共享同一dir且磁盘空间紧张,可能因竞争创建失败
替代方案:需要自定义权限或不立即打开文件时
如果明确不想一创建就打开文件,或需要非 0600 权限(比如让其他进程可读),就不能用 os.CreateTemp,而应组合使用 os.MkdirTemp + os.OpenFile:
dir, err := os.MkdirTemp("", "myapp-*")
if err != nil {
log.Fatal(err)
}
defer os.RemoveAll(dir)
filePath := filepath.Join(dir, "config.yaml")
f, err := os.OpenFile(filePath, os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
log.Fatal(err)
}
defer f.Close()
这种写法更灵活,但多了两步操作,日常临时文件场景优先选 os.CreateTemp。
真正容易被忽略的是:临时文件名里的随机段长度固定为 10 字符,且不含路径分隔符——所以别试图在 pattern 里写 "subdir/*.log",它只会创建在根临时目录下,"*" 不负责路径生成。









