英文:
idiomatic way to get os err after call
问题
如果我执行以下代码:
s, err := os.Stat(path)
并且 err != nil
,我需要知道是文件不存在还是我没有权限访问等等。我该如何获取底层的错误代码?阅读 os
包的文档,似乎建议我读取错误字符串的文本 - 这真的是这样吗?
英文:
If I do
s, err := os.Stat(path)
and err != nil
I need to know if the file doesn't exist vs I don't have permission to access it, etc. How do I get the underlying error code? Reading the os
package docs it seems to suggest that I read the text of the error string - surely not?
答案1
得分: 6
【FUZxxl说】。
从os.Stat
文档中:
> Stat返回描述指定文件的FileInfo
。如果发生错误,它将是*PathError
类型。
PathError
在同一页上有文档,说明它保存了导致错误的操作、导致错误的文件路径和底层系统的错误。如果在调用os.Stat
时找不到文件,返回的错误可能是这样的:
&PathError{"stat", "/your/file", syscall.Errno(2)}
由于底层错误本质上取决于您使用的操作系统,您唯一能做的就是理解PathError.Err
。对于UNIX系统,syscall
包具有由诸如syscall.Stat
之类的系统调用返回的Errno
错误类型。您可以将此值与syscall
包中的常量进行比较并处理错误(点击播放):
stat, err := os.Stat(file)
if perr, ok := err.(*os.PathError); ok {
switch perr.Err.(syscall.Errno) {
case syscall.ENOENT: fmt.Println("No such file or directory.")
default: panic("Unknown error")
}
}
更简洁的方法是使用os.IsNotExist
,它实际上就是上述操作,而且最重要的是与平台无关:
stat, err := os.Stat(file)
if err != nil && os.IsNotExist(err) {
// ...
}
英文:
What FUZxxl says.
From the os.Stat
documentation:
> Stat returns a FileInfo
describing the named file. If there is an error, it will be of type *PathError
.
PathError
is documented on the same page, stating that it holds the operation that caused the error, the path to the file that caused it and the underlying system's error. In case the file was not found when calling os.Stat
, the returned error would be something like this:
&PathError{"stat", "/your/file", syscall.Errno(2)}
Since the underlying error is inherently depending on the OS you use, the only thing that you can do is to
understand PathError.Err
. For UNIX systems the syscall
package has the Errno
error type returned by syscalls like syscall.Stat
. You can compare this value with the constants in the syscall
package and handle the error (Click to play):
stat, err := os.Stat(file)
if perr, ok := err.(*os.PathError); ok {
switch perr.Err.(syscall.Errno) {
case syscall.ENOENT: fmt.Println("No such file or directory.")
default: panic("Unknown error")
}
}
The shorter way of doing this is to use os.IsNotExist
which does pretty much the above
and is, most importantly, platform independent:
stat, err := os.Stat(file)
if err != nil && os.IsNotExist(err) {
// ...
}
答案2
得分: 1
另一个答案很好,但我想补充一下关于这个建议的说明:
stat, err := os.Stat(file)
if err != nil && os.IsNotExist(err) {
// ...
}
我发现在许多情况下,我需要根据每个测试采取不同的操作,所以实际上你有三个分支。这是我用于处理这种情况的代码:
stat, err := os.Stat(file)
if os.IsNotExist(err) {
// 第一个分支
} else if err != nil {
// 第二个分支
}
// 第三个分支
英文:
The other answer is great, but I wanted add a note about this suggestion:
stat, err := os.Stat(file)
if err != nil && os.IsNotExist(err) {
// ...
}
I found that in many cases, I was needing to take different actions depending on
each test, so in reality you have three branches here. Here is code I use for
that:
stat, err := os.Stat(file)
if os.IsNotExist(err) {
// branch one
} else if err != nil {
// branch two
}
// branch three
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论