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 5package fmt 6 7import ( 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. 22func 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 54type wrapError struct { 55 msg string 56 err error 57} 58 59func (e *wrapError) Error() string { 60 return e.msg 61} 62 63func (e *wrapError) Unwrap() error { 64 return e.err 65} 66 67type wrapErrors struct { 68 msg string 69 errs []error 70} 71 72func (e *wrapErrors) Error() string { 73 return e.msg 74} 75 76func (e *wrapErrors) Unwrap() []error { 77 return e.errs 78} 79