os.stat是获取文件元数据的唯一推荐入口,一次调用即可获取大小(info.size())、修改时间(info.modtime())、是否为目录(info.isdir())等全部属性;需区分os.stat(跟随符号链接)与os.lstat(获取链接自身),并妥善处理跨平台差异及各类错误。

os.Stat 是获取文件详细属性的唯一推荐入口,它一次系统调用就能拿到大小、权限、时间戳、类型等全部元数据;别拆成多个函数调用,也别指望 multipart.FileHeader 提供真实文件信息。
怎么用 os.Stat 拿到文件大小、修改时间、是否是目录
直接调 os.Stat,检查 err,然后从返回的 os.FileInfo 接口里取字段:
-
info.Size()返回int64字节数,对普通文件可靠,对目录或设备文件无意义(POSIX 行为) -
info.ModTime()是time.Time类型,跨平台比较时建议先.Truncate(time.Second)避免 FAT32/macOS 秒级精度差异 -
info.IsDir()判断是否为目录,比info.Mode().IsDir()更简洁;info.Mode().IsRegular()才是判断“普通文件”的正确方式 - 别用
strings.HasSuffix(info.Name(), ".log")当日志文件——后缀不决定类型,info.Mode().IsRegular()才反映本质
os.Stat 和 os.Lstat 的关键区别在哪
路径含符号链接时,行为完全不同:
-
os.Stat("link")返回的是链接指向的目标文件的元数据(比如目标是 10MB 的二进制,就返回它的大小和修改时间) -
os.Lstat("link")返回的是链接文件本身的元数据(Size()是目标路径字符串长度,Mode()包含os.ModeSymlink位) - 想确认一个路径是不是符号链接本身,必须用
os.Lstat,再判断info.Mode() & os.ModeSymlink != 0 - Windows 下硬链接、重解析点行为更复杂,
os.Lstat可能仍跟随,需结合syscall层判断
FileInfo.Mode() 权限位怎么安全解析
os.FileMode 是 uint32,高位存类型(如 os.ModeDir),低位存 Unix 权限(0o755),不能直接打印数值或字符串比较:
- 判断可执行:用
info.Mode().Perm() & 0o111 != 0(Perm()屏蔽类型位,只留权限) - 判断用户是否有写权限:
info.Mode().Perm() & 0o200 != 0 - 获取八进制权限字符串:
fmt.Sprintf("%o", info.Mode().Perm()) - Windows 下
Perm()基本无效(恒为0o444或0o666),别拿它做访问控制逻辑
上传文件时的元数据哪部分可信
multipart.FileHeader 是 HTTP 请求头解析结果,不是文件系统元数据,仅以下两项可直接信任:
-
fh.Size:服务端完整解析 multipart body 后的字节数,只要r.ParseMultipartForm成功就准确(注意:流式中断时可能偏小) -
fh.Header.Get("Content-Type"):仅作参考,浏览器常为空或填错,后续必须用http.DetectContentType检测前 512 字节 -
fh.Filename完全不可信——可能是"C:\fakepath\foo.jpg"、空字符串,或含路径遍历字符(../../etc/passwd),绝不能拼进本地路径 - 要真正获取上传文件的磁盘属性(比如大小、权限),得先保存到临时路径,再对那个路径调
os.Stat
真正麻烦的地方不在调用本身,而在于错误分类和平台差异:路径不存在、没权限、NFS 挂载异常、悬空符号链接,都会让 os.Stat 返回不同错误;Windows 创建时间、Linux 访问时间、macOS 时间戳精度,也都得各自兜底。别写死 if err != nil 就 panic。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











