os.OpenFile 的 perm 参数仅在文件不存在且标志含 os.O_CREATE 时生效,已存在文件权限不变;修改需显式调用 os.Chmod,注意 umask、跨平台差异及权限检查。

Go 中 os.OpenFile 的 perm 参数只在创建文件时生效
很多人误以为传给 os.OpenFile 的 perm(比如 0644)会影响已存在文件的权限,其实不会。该参数仅在标志位含 os.O_CREATE 且文件不存在时起作用。
- 若文件已存在,
perm被忽略,原权限保持不变 - 若用
os.Create(等价于os.OpenFile(..., os.O_CREATE|os.O_WRONLY|os.O_TRUNC, perm)),perm才真正应用 - Linux/macOS 下,实际创建的权限还受进程
umask影响(例如umask=0022会让0666 &^ 0022 = 0644)
修改已有文件权限必须显式调用 os.Chmod
想把一个已存在的文件改成可执行、只读或限制访问,不能靠打开方式,得单独调用 os.Chmod。
-
os.Chmod("config.json", 0600)—— 仅所有者可读写 -
os.Chmod("deploy.sh", 0755)—— 所有者可读写执行,组和其他人可读执行 - 注意:Windows 对大部分
chmod权限位不敏感(仅区分只读/非只读),0755和0644在 Windows 上效果可能一致 - 调用失败会返回 error,常见原因是权限不足(如非 root 修改系统目录下文件)或路径不存在
用 os.Stat 检查当前权限再决定是否修改
盲目 Chmod 可能覆盖用户预期设置,尤其在配置文件或共享环境中。建议先读取当前权限位做判断。
-
fi, err := os.Stat("data.bin"),然后fi.Mode().Perm()获取权限掩码 - 用位运算比对:例如
(fi.Mode().Perm() & 0100) != 0判断所有者是否有执行权 - 注意
fi.Mode()返回的是fs.FileMode,它包含权限位 + 类型位(如os.ModeDir、os.ModeSymlink),提取纯权限要用.Perm() - 符号链接需用
os.Lstat避免跟随,否则拿到的是目标文件的权限
跨平台处理权限时避免硬编码八进制字面量
直接写 0755 看似方便,但可读性差,也容易因缺少前导零被误认为十进制(Go 中 755 是十进制,0755 才是八进制)。更稳妥的方式是组合常量。
立即学习“go语言免费学习笔记(深入)”;
- 用
0o755(Go 1.13+ 支持)或fs.FileMode(0755)明确语义 - 组合权限:例如
fs.FileMode(0600) | fs.ModeSticky(虽然 sticky 通常只用于目录) - 对目录常用操作:
os.MkdirAll(path, 0o755)创建时设权限;os.Chmod(path, 0o700)后续收紧 - 容器或 CI 环境中,挂载卷的默认权限可能覆盖 Go 设置,此时需确认运行时 uid/gid 和挂载选项(如
uid=1001,gid=1001)
chmod 系统调用的解释,以及文件所在文件系统的支持程度(例如 FAT32 不支持 Unix 权限)。别只盯着 Go 代码,要结合部署环境一起看。










