Reputation: 6079
I have the following code (also at https://play.golang.org/p/9MlhhUPZRog ):
package main
import (
"errors"
"fmt"
"os"
)
func main() {
var pathError *os.PathError
// Generate the error
_, err := os.Open("I_DO_NOT_EXIST.TXT");
// Print, everything is OK here
fmt.Println(err);
// Wrap the error multiple times
err = fmt.Errorf("%w; another error", err)
err = fmt.Errorf("%w; another error", err)
// Is it path error?
fmt.Println(err, " ---- is path error? ----> ", errors.Is(err, pathError))
// !!! UNCOMMENT THE LINE BELOW TO SEE THE DIFFERENCE !!!
// if errors.As(err, &pathError) {}
// Is it path error now?
fmt.Println(err, " ---- is path error? ----> ", errors.Is(err, pathError))
}
Result is:
open I_DO_NOT_EXIST.TXT: no such file or directory
open I_DO_NOT_EXIST.TXT: no such file or directory; another error; another error ---- is path error? ----> false
open I_DO_NOT_EXIST.TXT: no such file or directory; another error; another error ---- is path error? ----> false
And it makes sense. However, if I uncomment the line if errors.As...
the result is completely different:
open I_DO_NOT_EXIST.TXT: no such file or directory
open I_DO_NOT_EXIST.TXT: no such file or directory; another error; another error ---- is path error? ----> false
open I_DO_NOT_EXIST.TXT: no such file or directory; another error; another error ---- is path error? ----> true
It says true
for the last check.
Why did errors.As
mutated the err
variable?
Upvotes: 0
Views: 6147
Reputation: 165
As per the documentation:
As unwraps its first argument sequentially looking for an error that can be assigned to its second argument, which must be a pointer. If it succeeds, it performs the assignment and returns true. Otherwise, it returns false.
Thus, when you do errors.As(err, &pathError)
, pathError gets set to err.
You can verify it by this code:
package main
import (
"errors"
"fmt"
"os"
)
func main() {
var pathError *os.PathError
// Generate the error
_, err := os.Open("I_DO_NOT_EXIST.TXT");
// Print, everything is OK here
fmt.Println(err);
//pathError is nil here
fmt.Println(pathError)
// Is it path error?
fmt.Println(err, " ---- is path error? ----> ", errors.Is(err, pathError))
fmt.Println()
//pathError is set to err here
if errors.As(err, &pathError) {}
fmt.Println(err);
//pathError as err here
fmt.Println(pathError)
// Is it path error?
fmt.Println(err, " ---- is path error? ----> ", errors.Is(err, pathError))
}
Upvotes: 9