Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

idiomatic way to get os err after call

Tags:

go

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?

like image 294
pm100 Avatar asked Jun 04 '14 17:06

pm100


2 Answers

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) {
    // ...
}
like image 146
nemo Avatar answered Sep 30 '22 17:09

nemo


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
like image 37
Zombo Avatar answered Sep 30 '22 19:09

Zombo