windows上os.open报error_path_not_found是因系统长路径限制,需同时启用注册表longpathsenabled并为go程序嵌入含longpathaware=true的manifest。

Windows 上 os.Open 报错 ERROR_PATH_NOT_FOUND 或路径截断,不是代码写错了
Go 程序在 Windows 上读写深层嵌套路径(比如 C:c...ile.txt 超过 260 字符)时,即使路径真实存在,os.Open 也可能直接返回 ERROR_PATH_NOT_FOUND。这不是 Go 的 bug,而是 Windows 默认启用的「传统 DOS 路径限制」在拦截——系统底层根本没把长路径传给 Go 运行时。
- Windows 默认限制是 MAX_PATH=260,且对大多数 Win32 API(包括 Go 调用的
CreateFileW)生效 - Go 1.16+ 已默认启用长路径支持(通过调用
\?前缀),但前提是系统和进程都允许 - 关键不在 Go 代码里加前缀,而在 Windows 系统配置和 Go 构建方式
go build 生成的二进制必须声明支持长路径(否则系统不放行)
仅靠 Go 源码里用 \?C:... 是不够的:Windows 会检查可执行文件的 manifest,没声明就拒绝传递长路径。Go 默认不嵌入 manifest,所以你得手动补上。
- 新建一个
app.manifest文件,内容必须包含:<application xmlns="urn:schemas-microsoft-com:asm.v3"> <windowsSettings> <longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware> </windowsSettings> </application> - 用
go build -ldflags "-H windowsgui -manifest app.manifest"构建(-H windowsgui可选,但能避免控制台闪退;若要控制台程序,去掉它) - 构建后可用
sigcheck -m yourapp.exe(Sysinternals 工具)验证 manifest 是否生效:看到longPathAware = true才算成功
Go 代码里要不要加 \? 前缀?看场景
加不加前缀,取决于你调用的是哪一层 API。Go 标准库多数函数(如 os.Open、os.Stat)内部已自动处理:只要 manifest 正确 + 系统开启策略,它们会悄悄转成 ? 调用。手动加反而容易出问题。
- ✅ 安全做法:直接传原始路径,例如
os.Open("C:\project\deep\nested\file.txt") - ❌ 不推荐:自己拼
"\\?\C:\project\...",因为\?路径不支持相对路径、不能含./..、不经过当前目录解析,极易触发invalid argument - ⚠️ 唯一需要手动加的场景:调用
syscall或unsafe直接调 Win32 API(比如FindFirstFileW),此时必须自己构造\?格式且确保路径绝对、无符号
系统级开关 LongPathsEnabled 必须打开(尤其 Server 版或旧版 Win10)
即使你的程序 manifest 正确、Go 版本够新,如果系统策略关着,一切白搭。这个开关控制所有进程是否被允许使用长路径,不是单个程序能绕过的。
立即学习“go语言免费学习笔记(深入)”;
- 检查方法:注册表路径
HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlFileSystemLongPathsEnabled,值应为DWORD=1 - 启用命令(管理员权限运行):
reg add "HKLMSYSTEMCurrentControlSetControlFileSystem" /v LongPathsEnabled /t REG_DWORD /d 1 /f - 注意:某些 Windows Server 版本默认关闭,且组策略可能覆盖注册表设置;企业环境需确认 GPO 中「启用 Win32 长路径」是否启用
最常被忽略的是 manifest 和系统开关的组合验证——缺一不可。单独改代码、单独改注册表、单独升级 Go,都不足以让长路径真正跑通。










