os.stat是获取文件权限和修改时间的首选方式,需用info.mode().perm()提取纯权限位(如0644)、info.modtime()获取time.time类型修改时间,并严格检查error;os.chmod改权限时必须传八进制字面量(如0644)。

直接用 os.Stat 读权限、os.Chmod 改权限,是最简稳方案;别碰 syscall.Stat_t,也别传十进制数字当权限值。
怎么用 os.Stat 安全读取权限和修改时间
os.Stat 一次调用就返回完整元数据,不需要拆成多次系统调用。关键点在于:用 info.Mode().Perm() 提取纯权限位(比如 0644),而不是直接拿 info.Mode() 做数值比较 —— 因为后者包含目录标志(如 0x8000),info.Mode() == 0644 永远不成立。
- 判断是否可执行:
info.Mode().Perm() & 0111 != 0(注意是八进制0111,不是0x111) - 获取修改时间:
info.ModTime()返回time.Time,别用纳秒值做相等比较,跨文件系统精度不一致 - 检查错误必须写:
if err != nil { /* 处理 os.IsNotExist(err) 等 */ },err == nil才能放心用info - 符号链接默认跟随目标 —— 如果你关心的是链接本身(而非它指向的文件),该用
os.Lstat,但绝大多数场景用os.Stat就对了
os.Chmod 的权限值必须是八进制字面量
传 644 是错的,必须写 0644。Go 编译器把前导 0 当作八进制解析,644 是十进制,二进制低 9 位完全不对,结果权限会乱。
初始化并管理阿里云SDK Go 客户端,涵盖 sync.Once 单例、goroutine 安全、endpoint 与 region 配置、VPC 端点及调试。
- 硬编码权限:始终用
0600、0755、0444这种带前导0的写法 - 从字符串解析(如配置项):
perm, err := strconv.ParseInt(s, 8, 32),不能用strconv.Atoi - 验证是否正确:
fmt.Printf("%o", perm)应该输出600,而不是384(那是十进制 384 的八进制表示) - Windows 下
0600表示只读,0644表示可读写;执行位(x)无效,别依赖它做逻辑分支
修改已有文件权限前要预检
os.Chmod 返回 nil 不代表成功 —— 它可能静默失败,尤其在非普通文件、属主不匹配或只读文件系统上。
- 先确认是普通文件:
if !info.Mode().IsRegular() { /* 拒绝操作 */ } - 路径不是符号链接(除非你明确想改目标):符号链接本身权限需用
os.Lchmod(仅 Unix-like 系统支持) - 当前用户是文件所有者:否则 Linux/macOS 下大概率报
operation not permitted;可用info.Sys().(*syscall.Stat_t).Uid对比os.Getuid() - 父目录可写:权限修改本质是修改 inode 元数据,需要对父目录有写权限,否则即使文件可写也会失败
创建文件时就设权限比事后 Chmod 更安全
敏感文件(如密钥、token、配置)一旦以宽松权限(如 0644)落地再改,存在被其他进程短暂读取的风险。
- 用
os.WriteFile(path, data, 0600)一步到位 - 用
os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0600)创建并打开 -
os.OpenFile的perm参数只在O_CREATE时生效,文件已存在时完全忽略 - umask 会影响最终权限:Go 不自动应用 umask,你给
0666,实际可能是0644(取决于当前 umask),若需精确控制,得自己算或用syscall.Umask临时调整
权限值是八进制、文件类型要靠 IsDir() 判断、修改前必须确认属主和文件类型 —— 这些不是细节,是 Unix 权限模型里绕不开的硬约束。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










