判斷一個檔案是否存在是一個相當常見的需求,在golang中也有多種方案實現這一功能。
現在我們介紹其中兩種最常用也是最簡單的實現,第一種將是跨平臺通用的,而第二種則在POSIX平臺上通用。
跨平臺實現
跨平臺實現的思路很簡單,如果某個檔案不存在,那麼使用os.Lstat
就一定會返回error,只要判斷error是否代表檔案不存在即可。
也許你注意到了有些程式碼會使用os.Open
來完成上述工作,不過最好不要這麼做,因為雖然兩者完成的功能沒有區別,但open和stat的呼叫開銷是不同的,後者要小於前者,而且對於判斷檔案是否存在,檢查它的後設資料要比直接嘗試開啟它更加合理。
那麼來看看實現的程式碼:
func FileExist(path string) bool {
_, err := os.Lstat(path)
return !os.IsNotExist(err)
}
程式碼很簡單,對於Windows/Linux/MacOS等是通用的,一般沒有特殊需求我也比較推薦這種實現。
POSIX平臺實現
如果你的程式是面向POSIX平臺的(例如UNIX、Linux等),那麼還有一種更簡單的方案——syscall.Access
。
syscall.Access
提供了使用者檢查檔案元資訊的手段,通常它被用來檢查檔案許可權以及檔案的存在性。
通過使用syscall.F_OK
標誌檢查檔案,如果不存在則會返回和os.Lstat
一樣的error:
func FileExist(path string) bool {
err := syscall.Access(path, syscall.F_OK)
return !os.IsNotExist(err)
}
這種實現的最大優勢在於它簡單而直觀,但是它無法在Windows上使用。
一點提示
當我們的FileExist
返回true時,其實檔案並不一定存在。
當我們對目標path中的某一部分沒有可讀許可權時,os.Lstat
和syscall.Access
同樣會返回error,不過這個error不會讓os.IsNotExist
返回true。
當檔案不存在而你對檔案所在的目錄或者它的上層目錄沒有訪問許可權時,FileExist
依舊會返回true,bug就在這時發生了。
所以重要的一點是在判斷檔案是否存在前應該先判斷自己對檔案及其路徑是否有訪問許可權。