os.stat 一次调用即可获取完整文件属性,包括 size()、modtime()、mode() 及 isdir()、isregular() 等安全判断方法;需用 mode().perm() 提取纯权限位,避免直接比较掩码;权限检查不能依赖 stat 结果,应直接尝试操作验证。

os.Stat 能拿到哪些文件属性,一次调用就够了
os.Stat 是 Go 中获取文件元数据的唯一推荐入口,它一次系统调用就返回完整信息,不用拆成 size、modtime、mode 多次查。返回的 os.FileInfo 接口里有:Size()(逻辑字节数)、ModTime()(time.Time 类型,注意是本地时区)、Mode()(含类型和权限位的 os.FileMode)、IsDir()、Mode().IsRegular() 等安全判断方法。
常见错误是以为 os.Stat 只能拿修改时间——其实它全都有;也别自己封装 syscall.Stat,跨平台行为(比如 Windows 的硬链接、macOS 的 birthtime)标准库已处理好。
必须检查 error:err == nil 才能放心用 fileInfo;若失败,先用 errors.Is(err, os.ErrNotExist) 判断是否真不存在,而不是直接认为“没权限”或“路径错”。
权限位怎么安全解析,别手写 0644 比较
fileInfo.Mode() 返回的是带文件类型(如 os.ModeDir、os.ModeSymlink)的完整位掩码,高位不是权限,直接 == 0644 或 & 0200 会误判。正确做法是先调 fileInfo.Mode().Perm() 提取低 9 位纯 Unix 权限,再做位运算:
- 用户可读:
fileInfo.Mode().Perm() & 0400 != 0 - 用户可写:
fileInfo.Mode().Perm() & 0200 != 0 - 用户可执行:
fileInfo.Mode().Perm() & 0100 != 0 - 判断是否为普通文件:
fileInfo.Mode().IsRegular()(比后缀判断可靠)
Windows 下 .Perm() 恒为 0444 或 0666,不反映真实 ACL,别拿它做访问控制逻辑;Linux/macOS 也需注意:即使权限显示可写,父目录缺 x 权限(无法进入)或挂载为只读(mount -o ro),实际仍写不了。
os.Stat 不等于“我能操作这个文件”,真实权限得试
os.Stat 只读元数据,不验证当前进程是否真能读写。比如:
初始化并管理阿里云SDK Go 客户端,涵盖 sync.Once 单例、goroutine 安全、endpoint 与 region 配置、VPC 端点及调试。
- 文件权限是
0644,但父目录没 x 权限 →open直接失败 - 文件系统挂载为只读 → 所有写操作返回
os.ErrPermission - SELinux/ACL 限制 →
os.Stat完全看不到
更可靠的方式是直接尝试操作:os.OpenFile(path, os.O_RDONLY, 0) 测可读,os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0600) 测可写+可创建。注意 os.O_EXCL 会因文件存在而报 os.ErrExist,适合“新建场景”;对已有文件,去掉它即可。
Linux/macOS 下可用 golang.org/x/sys/unix.Access(path, unix.W_OK) 模拟 shell 的 [ -w ] 行为(检查整条路径),但它不跨平台,且仍有竞态风险——检查通过后权限可能立刻被改掉。
符号链接要用 os.Lstat,别混淆目标和链接本身
路径含符号链接时,os.Stat("link") 返回的是目标文件的元数据(比如目标是 1GB 的二进制,Size() 就是 1GB);而 os.Lstat("link") 返回的是链接文件自身的元数据(Size() 是目标路径字符串长度,Mode() 含 os.ModeSymlink 位)。
想确认一个路径是不是符号链接本身,必须用 os.Lstat,再判断:info.Mode() & os.ModeSymlink != 0。Windows 下重解析点行为更复杂,os.Lstat 有时仍会跟随,此时需结合 syscall 层进一步判断。
真正难的不是写对那几行位运算,而是意识到权限是动态的、分层的、受挂载选项和安全模块约束的——os.Stat 给你的只是快照,不是承诺。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










