Source file src/errors/example_test.go

     1  // Copyright 2012 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package errors_test
     6  
     7  import (
     8  	"errors"
     9  	"fmt"
    10  	"io/fs"
    11  	"os"
    12  	"time"
    13  )
    14  
    15  // MyError is an error implementation that includes a time and message.
    16  type MyError struct {
    17  	When time.Time
    18  	What string
    19  }
    20  
    21  func (e MyError) Error() string {
    22  	return fmt.Sprintf("%v: %v", e.When, e.What)
    23  }
    24  
    25  func oops() error {
    26  	return MyError{
    27  		time.Date(1989, 3, 15, 22, 30, 0, 0, time.UTC),
    28  		"the file system has gone away",
    29  	}
    30  }
    31  
    32  func Example() {
    33  	if err := oops(); err != nil {
    34  		fmt.Println(err)
    35  	}
    36  	// Output: 1989-03-15 22:30:00 +0000 UTC: the file system has gone away
    37  }
    38  
    39  func ExampleNew() {
    40  	err := errors.New("emit macho dwarf: elf header corrupted")
    41  	if err != nil {
    42  		fmt.Print(err)
    43  	}
    44  	// Output: emit macho dwarf: elf header corrupted
    45  }
    46  
    47  func OopsNew() error {
    48  	return errors.New("an error")
    49  }
    50  
    51  var ErrSentinel = errors.New("an error")
    52  
    53  func OopsSentinel() error {
    54  	return ErrSentinel
    55  }
    56  
    57  // Each call to [errors.New] returns an unique instance of the error,
    58  // even if the arguments are the same. To match against errors
    59  // created by [errors.New], declare a sentinel error and reuse it.
    60  func ExampleNew_unique() {
    61  	err1 := OopsNew()
    62  	err2 := OopsNew()
    63  	fmt.Println("Errors using distinct errors.New calls:")
    64  	fmt.Printf("Is(%q, %q) = %v\n", err1, err2, errors.Is(err1, err2))
    65  
    66  	err3 := OopsSentinel()
    67  	err4 := OopsSentinel()
    68  	fmt.Println()
    69  	fmt.Println("Errors using a sentinel error:")
    70  	fmt.Printf("Is(%q, %q) = %v\n", err3, err4, errors.Is(err3, err4))
    71  
    72  	// Output:
    73  	// Errors using distinct errors.New calls:
    74  	// Is("an error", "an error") = false
    75  	//
    76  	// Errors using a sentinel error:
    77  	// Is("an error", "an error") = true
    78  }
    79  
    80  // The fmt package's Errorf function lets us use the package's formatting
    81  // features to create descriptive error messages.
    82  func ExampleNew_errorf() {
    83  	const name, id = "bimmler", 17
    84  	err := fmt.Errorf("user %q (id %d) not found", name, id)
    85  	if err != nil {
    86  		fmt.Print(err)
    87  	}
    88  	// Output: user "bimmler" (id 17) not found
    89  }
    90  
    91  func ExampleJoin() {
    92  	err1 := errors.New("err1")
    93  	err2 := errors.New("err2")
    94  	err := errors.Join(err1, err2)
    95  	fmt.Println(err)
    96  	if errors.Is(err, err1) {
    97  		fmt.Println("err is err1")
    98  	}
    99  	if errors.Is(err, err2) {
   100  		fmt.Println("err is err2")
   101  	}
   102  	fmt.Println(err.(interface{ Unwrap() []error }).Unwrap())
   103  	// Output:
   104  	// err1
   105  	// err2
   106  	// err is err1
   107  	// err is err2
   108  	// [err1 err2]
   109  }
   110  
   111  func ExampleIs() {
   112  	if _, err := os.Open("non-existing"); err != nil {
   113  		if errors.Is(err, fs.ErrNotExist) {
   114  			fmt.Println("file does not exist")
   115  		} else {
   116  			fmt.Println(err)
   117  		}
   118  	}
   119  
   120  	// Output:
   121  	// file does not exist
   122  }
   123  
   124  type MyIsError struct {
   125  	err string
   126  }
   127  
   128  func (e MyIsError) Error() string {
   129  	return e.err
   130  }
   131  func (e MyIsError) Is(err error) bool {
   132  	return err == fs.ErrPermission
   133  }
   134  
   135  // Custom errors can implement a method "Is(error) bool" to match other error values,
   136  // overriding the default matching of [errors.Is].
   137  func ExampleIs_custom_match() {
   138  	var err error = MyIsError{"an error"}
   139  	fmt.Println("Error equals fs.ErrPermission:", err == fs.ErrPermission)
   140  	fmt.Println("Error is fs.ErrPermission:", errors.Is(err, fs.ErrPermission))
   141  
   142  	// Output:
   143  	// Error equals fs.ErrPermission: false
   144  	// Error is fs.ErrPermission: true
   145  }
   146  
   147  func ExampleAs() {
   148  	if _, err := os.Open("non-existing"); err != nil {
   149  		var pathError *fs.PathError
   150  		if errors.As(err, &pathError) {
   151  			fmt.Println("Failed at path:", pathError.Path)
   152  		} else {
   153  			fmt.Println(err)
   154  		}
   155  	}
   156  
   157  	// Output:
   158  	// Failed at path: non-existing
   159  }
   160  
   161  func ExampleAsType() {
   162  	if _, err := os.Open("non-existing"); err != nil {
   163  		if pathError, ok := errors.AsType[*fs.PathError](err); ok {
   164  			fmt.Println("Failed at path:", pathError.Path)
   165  		} else {
   166  			fmt.Println(err)
   167  		}
   168  	}
   169  	// Output:
   170  	// Failed at path: non-existing
   171  }
   172  
   173  type MyAsError struct {
   174  	err string
   175  }
   176  
   177  func (e MyAsError) Error() string {
   178  	return e.err
   179  }
   180  func (e MyAsError) As(target any) bool {
   181  	pe, ok := target.(**fs.PathError)
   182  	if !ok {
   183  		return false
   184  	}
   185  	*pe = &fs.PathError{
   186  		Op:   "custom",
   187  		Path: "/",
   188  		Err:  errors.New(e.err),
   189  	}
   190  	return true
   191  }
   192  
   193  // Custom errors can implement a method "As(any) bool" to match against other error types,
   194  // overriding the default matching of [errors.As].
   195  func ExampleAs_custom_match() {
   196  	var err error = MyAsError{"an error"}
   197  	fmt.Println("Error:", err)
   198  	fmt.Printf("TypeOf err: %T\n", err)
   199  
   200  	var pathError *fs.PathError
   201  	ok := errors.As(err, &pathError)
   202  	fmt.Println("Error as fs.PathError:", ok)
   203  	fmt.Println("fs.PathError:", pathError)
   204  
   205  	// Output:
   206  	// Error: an error
   207  	// TypeOf err: errors_test.MyAsError
   208  	// Error as fs.PathError: true
   209  	// fs.PathError: custom /: an error
   210  }
   211  
   212  // Custom errors can implement a method "As(any) bool" to match against other error types,
   213  // overriding the default matching of [errors.AsType].
   214  func ExampleAsType_custom_match() {
   215  	var err error = MyAsError{"an error"}
   216  	fmt.Println("Error:", err)
   217  	fmt.Printf("TypeOf err: %T\n", err)
   218  
   219  	pathError, ok := errors.AsType[*fs.PathError](err)
   220  	fmt.Println("Error as fs.PathError:", ok)
   221  	fmt.Println("fs.PathError:", pathError)
   222  
   223  	// Output:
   224  	// Error: an error
   225  	// TypeOf err: errors_test.MyAsError
   226  	// Error as fs.PathError: true
   227  	// fs.PathError: custom /: an error
   228  }
   229  
   230  func ExampleUnwrap() {
   231  	err1 := errors.New("error1")
   232  	err2 := fmt.Errorf("error2: [%w]", err1)
   233  	fmt.Println(err2)
   234  	fmt.Println(errors.Unwrap(err2))
   235  	// Output:
   236  	// error2: [error1]
   237  	// error1
   238  }
   239  

View as plain text