github.com/mtsmfm/go/src@v0.0.0-20221020090648-44bdcb9f8fde/fmt/errors.go (about) 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 "sort" 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 sort.Ints(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 }