When I use ioutil
to read a file, it may return an error. But if I want to filter some error code, what should I do?
res, err := ioutil.ReadFile("xxx")
if err != nil {
fmt.Println(err.Error())
}
...
In the code snippet above, when a file has no permission, fmt.Println(err.Error())
will print "open xxxxx: permission denied
. If I want to capture this kind error, how can I know that file read failed because permission was denied?
Should I search err.Error()
for the string permission denied
- this looks ungraceful. Is there any better way?
Thanks in advance.
Update
After trying @Intermernet solution, I found that it will not hit case os.ErrPermission
, it will hit default
and print "open xxx: Permission denied"
.
@Aedolon solution is ok, os.IsPermission(err)
can tell that a file has failed with permission deny.
According to the current API, ioutil.ReadFile
doesn't guarantee any specific behaviour except that it will return err == nil
when successful. Even the syscall package doesn't actually guarantee a specific error.
The current implementation of ioutil.ReadFile
uses os.Open
, which will return *os.PathError
when failing to open a file, not os.ErrPermission
or anything else. os.PathError
contains a field Err
which is also an error - in this case, a syscall.Errno
. The string "permission denied" is produced from a private table of error messages and it's both architecture and implementation-specific. In my Windows machine it says "Access is denied" instead.
AFAIK, the correct method is to use os.IsPermission(err)
, which will return true
in case of lacking permissions.
ioutil.ReadFile()
calls os.Open()
and returns any error encountered there.
The os
package defines some file related errors.
ErrInvalid = errors.New("invalid argument")
ErrPermission = errors.New("permission denied")
ErrExist = errors.New("file already exists")
ErrNotExist = errors.New("file does not exist")
The one you're after is os.ErrPermission
.
res, err := ioutil.ReadFile("xxx")
if err != nil {
switch err {
case os.ErrInvalid:
//Do stuff
case os.ErrPermission:
//Do stuff
case os.ErrNotExist:
//Do stuff
default:
fmt.Println(err)
}
}