mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
errors: add examples for custom Is/As matching
Change-Id: Ia92dae13b6a4e9434b29d2ab3f698f6ba87b4b89 Reviewed-on: https://go-review.googlesource.com/c/go/+/713740 Reviewed-by: Damien Neil <dneil@google.com> Reviewed-by: Mark Freeman <markfreeman@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Auto-Submit: Damien Neil <dneil@google.com>
This commit is contained in:
parent
ec92bc6d63
commit
1903782ade
1 changed files with 113 additions and 0 deletions
|
|
@ -44,6 +44,39 @@ func ExampleNew() {
|
||||||
// Output: emit macho dwarf: elf header corrupted
|
// Output: emit macho dwarf: elf header corrupted
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func OopsNew() error {
|
||||||
|
return errors.New("an error")
|
||||||
|
}
|
||||||
|
|
||||||
|
var ErrSentinel = errors.New("an error")
|
||||||
|
|
||||||
|
func OopsSentinel() error {
|
||||||
|
return ErrSentinel
|
||||||
|
}
|
||||||
|
|
||||||
|
// Each call to [errors.New] returns an unique instance of the error,
|
||||||
|
// even if the arguments are the same. To match against errors
|
||||||
|
// created by [errors.New], declare a sentinel error and reuse it.
|
||||||
|
func ExampleNew_unique() {
|
||||||
|
err1 := OopsNew()
|
||||||
|
err2 := OopsNew()
|
||||||
|
fmt.Println("Errors using distinct errors.New calls:")
|
||||||
|
fmt.Printf("Is(%q, %q) = %v\n", err1, err2, errors.Is(err1, err2))
|
||||||
|
|
||||||
|
err3 := OopsSentinel()
|
||||||
|
err4 := OopsSentinel()
|
||||||
|
fmt.Println()
|
||||||
|
fmt.Println("Errors using a sentinel error:")
|
||||||
|
fmt.Printf("Is(%q, %q) = %v\n", err3, err4, errors.Is(err3, err4))
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// Errors using distinct errors.New calls:
|
||||||
|
// Is("an error", "an error") = false
|
||||||
|
//
|
||||||
|
// Errors using a sentinel error:
|
||||||
|
// Is("an error", "an error") = true
|
||||||
|
}
|
||||||
|
|
||||||
// The fmt package's Errorf function lets us use the package's formatting
|
// The fmt package's Errorf function lets us use the package's formatting
|
||||||
// features to create descriptive error messages.
|
// features to create descriptive error messages.
|
||||||
func ExampleNew_errorf() {
|
func ExampleNew_errorf() {
|
||||||
|
|
@ -88,6 +121,29 @@ func ExampleIs() {
|
||||||
// file does not exist
|
// file does not exist
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type MyIsError struct {
|
||||||
|
err string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e MyIsError) Error() string {
|
||||||
|
return e.err
|
||||||
|
}
|
||||||
|
func (e MyIsError) Is(err error) bool {
|
||||||
|
return err == fs.ErrPermission
|
||||||
|
}
|
||||||
|
|
||||||
|
// Custom errors can implement a method "Is(error) bool" to match other error values,
|
||||||
|
// overriding the default matching of [errors.Is].
|
||||||
|
func ExampleIs_custom_match() {
|
||||||
|
var err error = MyIsError{"an error"}
|
||||||
|
fmt.Println("Error equals fs.ErrPermission:", err == fs.ErrPermission)
|
||||||
|
fmt.Println("Error is fs.ErrPermission:", errors.Is(err, fs.ErrPermission))
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// Error equals fs.ErrPermission: false
|
||||||
|
// Error is fs.ErrPermission: true
|
||||||
|
}
|
||||||
|
|
||||||
func ExampleAs() {
|
func ExampleAs() {
|
||||||
if _, err := os.Open("non-existing"); err != nil {
|
if _, err := os.Open("non-existing"); err != nil {
|
||||||
var pathError *fs.PathError
|
var pathError *fs.PathError
|
||||||
|
|
@ -114,6 +170,63 @@ func ExampleAsType() {
|
||||||
// Failed at path: non-existing
|
// Failed at path: non-existing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type MyAsError struct {
|
||||||
|
err string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e MyAsError) Error() string {
|
||||||
|
return e.err
|
||||||
|
}
|
||||||
|
func (e MyAsError) As(target any) bool {
|
||||||
|
pe, ok := target.(**fs.PathError)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
*pe = &fs.PathError{
|
||||||
|
Op: "custom",
|
||||||
|
Path: "/",
|
||||||
|
Err: errors.New(e.err),
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Custom errors can implement a method "As(any) bool" to match against other error types,
|
||||||
|
// overriding the default matching of [errors.As].
|
||||||
|
func ExampleAs_custom_match() {
|
||||||
|
var err error = MyAsError{"an error"}
|
||||||
|
fmt.Println("Error:", err)
|
||||||
|
fmt.Printf("TypeOf err: %T\n", err)
|
||||||
|
|
||||||
|
var pathError *fs.PathError
|
||||||
|
ok := errors.As(err, &pathError)
|
||||||
|
fmt.Println("Error as fs.PathError:", ok)
|
||||||
|
fmt.Println("fs.PathError:", pathError)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// Error: an error
|
||||||
|
// TypeOf err: errors_test.MyAsError
|
||||||
|
// Error as fs.PathError: true
|
||||||
|
// fs.PathError: custom /: an error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Custom errors can implement a method "As(any) bool" to match against other error types,
|
||||||
|
// overriding the default matching of [errors.AsType].
|
||||||
|
func ExampleAsType_custom_match() {
|
||||||
|
var err error = MyAsError{"an error"}
|
||||||
|
fmt.Println("Error:", err)
|
||||||
|
fmt.Printf("TypeOf err: %T\n", err)
|
||||||
|
|
||||||
|
pathError, ok := errors.AsType[*fs.PathError](err)
|
||||||
|
fmt.Println("Error as fs.PathError:", ok)
|
||||||
|
fmt.Println("fs.PathError:", pathError)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// Error: an error
|
||||||
|
// TypeOf err: errors_test.MyAsError
|
||||||
|
// Error as fs.PathError: true
|
||||||
|
// fs.PathError: custom /: an error
|
||||||
|
}
|
||||||
|
|
||||||
func ExampleUnwrap() {
|
func ExampleUnwrap() {
|
||||||
err1 := errors.New("error1")
|
err1 := errors.New("error1")
|
||||||
err2 := fmt.Errorf("error2: [%w]", err1)
|
err2 := fmt.Errorf("error2: [%w]", err1)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue