判斷一個文件是否存在是一個相當常見的需求,在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就在這時發生了。
所以重要的一點是在判斷文件是否存在前應該先判斷自己對文件及其路徑是否有訪問權限。