通过os.Rename
返回的错误是*os.LinkError
类型,让你从操作系统访问底层错误的。你应该能够使用它来区分你遇到的特定错误。
您需要首先将错误转换为* os.LinkError。
例如,试图将一个文件夹(/Users/t/pprof
)到另一个名称是写保护(/Users/t/pprof2
)重命名:
func TestRename(t *testing.T) {
err := os.Rename("/Users/t/pprof", "/Users/t/pprof2")
if err != nil {
e := err.(*os.LinkError)
t.Logf("Op: ", e.Op)
t.Logf("Old: ", e.Old)
t.Logf("New: ", e.New)
t.Logf("Err: ", e.Err)
}
}
提供以下的输出:
Op: %!(EXTRA string=rename)
Old: %!(EXTRA string=/Users/t/pprof)
New: %!(EXTRA string=/Users/t/pprof2)
Err: %!(EXTRA syscall.Errno=operation not permitted)
的操作系统错误代码可作为Err
成员访问,但取决于您正在运行的操作系统会有所不同。
Err
成员的类型为syscall.Errno
。为了进一步检查实际的错误,你需要把它转换成该类型第一:
oserr := e.Err.(syscall.Errno)
现在oserr
可以在syscall
包申报Errno
的值进行比较。如果您在该页面上搜索ENOENT
,则会找到它们。
例如,你可以通过做检查您的特定错误:
switch oserr {
case syscall.ENOENT:
// Handle this error
default:
// Handle other errors
}
}
一般情况下,这是非常方便的调试这些问题的排序时使用fmt.Printf。在上面的例子:
fmt.Println(err)
打印
rename /Users/t/pprof /Users/t/pprof2: operation not permitted
其中,作为
fmt.Printf("%#v\n", err)
打印
&os.LinkError{Op:"rename", Old:"/Users/t/pprof", New:"/Users/t/pprof2", Err:0x1}
实际误差透露更多细节,而不仅仅是它的字符串表示。
我怀疑你可以从Go中的'err'中获得更多细节。但是,如果遇到这个问题,我会使用像perfmon这样的工具来找出什么是锁定文件,然后尝试在我的应用程序代码之外解决它 - 或者可能是代码更改 - 但是如果两个单独的应用程序共享文件您必须使用外部程序来协调它们,例如编写锁定文件。我粗略浏览了Go的'os'包,告诉我没有什么可以直接给你这个信息。 – evanmcdonnal
@evanmcdonnal感谢您的输入。我知道如何使用sysinternals来找出哪个进程导致问题。我的目标是检测原因并向用户提示可能导致问题的提示 – Marged
如果您有一些可以从命令行运行的东西,那么您可以使用Go的执行库(https://golang.org/pkg/os/ exec /)从您的应用程序中调用它,从std.out读取输出,解析锁定文件的其他应用程序的列表,然后将其显示给用户。 – evanmcdonnal