通過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