Source file src/fmt/errors.go

     1  // Copyright 2018 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 fmt
     6  
     7  import (
     8  	"errors"
     9  	"slices"
    10  )
    11  
    12  // Errorf formats according to a format specifier and returns the string as a
    13  // value that satisfies error.
    14  //
    15  // If the format specifier includes a %w verb with an error operand,
    16  // the returned error will implement an Unwrap method returning the operand.
    17  // If there is more than one %w verb, the returned error will implement an
    18  // Unwrap method returning a []error containing all the %w operands in the
    19  // order they appear in the arguments.
    20  // It is invalid to supply the %w verb with an operand that does not implement
    21  // the error interface. The %w verb is otherwise a synonym for %v.
    22  func Errorf(format string, a ...any) error {
    23  	p := newPrinter()
    24  	p.wrapErrs = true
    25  	p.doPrintf(format, a)
    26  	s := string(p.buf)
    27  	var err error
    28  	switch len(p.wrappedErrs) {
    29  	case 0:
    30  		err = errors.New(s)
    31  	case 1:
    32  		w := &wrapError{msg: s}
    33  		w.err, _ = a[p.wrappedErrs[0]].(error)
    34  		err = w
    35  	default:
    36  		if p.reordered {
    37  			slices.Sort(p.wrappedErrs)
    38  		}
    39  		var errs []error
    40  		for i, argNum := range p.wrappedErrs {
    41  			if i > 0 && p.wrappedErrs[i-1] == argNum {
    42  				continue
    43  			}
    44  			if e, ok := a[argNum].(error); ok {
    45  				errs = append(errs, e)
    46  			}
    47  		}
    48  		err = &wrapErrors{s, errs}
    49  	}
    50  	p.free()
    51  	return err
    52  }
    53  
    54  type wrapError struct {
    55  	msg string
    56  	err error
    57  }
    58  
    59  func (e *wrapError) Error() string {
    60  	return e.msg
    61  }
    62  
    63  func (e *wrapError) Unwrap() error {
    64  	return e.err
    65  }
    66  
    67  type wrapErrors struct {
    68  	msg  string
    69  	errs []error
    70  }
    71  
    72  func (e *wrapErrors) Error() string {
    73  	return e.msg
    74  }
    75  
    76  func (e *wrapErrors) Unwrap() []error {
    77  	return e.errs
    78  }
    79  

View as plain text