Go的标准库并没有专门用来检查文件是否存在的函数(就像Python的os.path.exists)。惯用的做法是什么?
当前回答
首先要考虑的是,您很少只想检查一个文件是否存在。在大多数情况下,如果文件存在,您将尝试对它做一些事情。在Go中,每当你试图对一个不存在的文件执行一些操作时,结果应该是一个特定的错误(os.ErrNotExist),最好的方法是检查返回的err值(例如在调用os.OpenFile(…)这样的函数时)是否为os.ErrNotExist。
这样做的推荐方法是:
file, err := os.OpenFile(...)
if os.IsNotExist(err) {
// handle the case where the file doesn't exist
}
但是,由于添加了错误。在Go 1.13(2019年底发布)中,新的建议是使用错误。是:
file, err := os.OpenFile(...)
if errors.Is(err, os.ErrNotExist) {
// handle the case where the file doesn't exist
}
通常最好避免使用os。在尝试对文件做一些事情之前,Stat检查文件是否存在,因为在对文件做一些事情之前,文件总是有可能被重命名、删除等。
然而,如果你接受这个警告,你真的,真的只是想检查一个文件是否存在,而不是继续对它做一些有用的事情(作为一个人为的例子,假设你正在编写一个毫无意义的CLI工具,告诉你一个文件是否存在,然后退出¯\_()_/¯),那么推荐的方法是:
if _, err := os.Stat(filename); errors.Is(err, os.ErrNotExist) {
// file does not exist
} else {
// file exists
}
其他回答
你应该使用os.Stat()和os.IsNotExist()函数,如下例所示:
func Exists(name string) (bool, error) {
_, err := os.Stat(name)
if err == nil {
return true, nil
}
if errors.Is(err, os.ErrNotExist) {
return false, nil
}
return false, err
}
修正了在某些情况下返回true的问题。 edit2:从os.IsNotExist()切换到使用errors.Is(),许多人说这是最佳实践
检查一个文件是否不存在,相当于Python的if not os.path.exists(filename):
if _, err := os.Stat("/path/to/whatever"); errors.Is(err, os.ErrNotExist) {
// path/to/whatever does not exist
}
检查一个文件是否存在,相当于Python的if os.path.exists(filename):
编辑:根据最近的评论
if _, err := os.Stat("/path/to/whatever"); err == nil {
// path/to/whatever exists
} else if errors.Is(err, os.ErrNotExist) {
// path/to/whatever does *not* exist
} else {
// Schrodinger: file may or may not exist. See err for details.
// Therefore, do *NOT* use !os.IsNotExist(err) to test for file existence
}
基本上
package main
import (
"fmt"
"os"
)
func fileExists(path string) bool {
_, err := os.Stat(path)
return !os.IsNotExist(err)
}
func main() {
var file string = "foo.txt"
exist := fileExists(file)
if exist {
fmt.Println("file exist")
} else {
fmt.Println("file not exists")
}
}
运行示例
另一种方法
与操作系统。开放
package main
import (
"fmt"
"os"
)
func fileExists(path string) bool {
_, err := os.Open(path) // For read access.
return err == nil
}
func main() {
fmt.Println(fileExists("d4d.txt"))
}
运行它
其他答案忽略的是,给函数的路径实际上可能是一个目录。下面的函数确保,路径确实是一个文件。
func fileExists(filename string) bool {
info, err := os.Stat(filename)
if os.IsNotExist(err) {
return false
}
return !info.IsDir()
}
另一件需要指出的事情是:这段代码仍然可能导致竞态条件,即在fileExists函数运行时,另一个线程或进程删除或创建指定的文件。
如果您担心这一点,可以在线程中使用锁,序列化对该函数的访问,或者在涉及多个应用程序时使用进程间信号量。如果涉及到其他应用程序,超出了您的控制范围,我想您就不走运了。
检查文件是否存在的最佳方法:
if _, err := os.Stat("/path/to/file"); err == nil || os.IsExist(err) {
// your code here if file exists
}