In Go, the function fmt.Errorf()
returns an error interface.
What's the proper way to check if fmt.Errorf()
itself failed?
Errorf
formats according to a format specifier and returns the string as a value that satisfies error. The fmt package's Errorf function lets us use the package's formatting features to create descriptive error messages.
func Errorf(format string, a ...interface{}) error {
return errors.New(Sprintf(format, a...))
}
And New
returns an error that formats as the given text.
func New(text string) error {
return &errorString{text}
}
And errorString
is a trivial implementation of error.
type errorString struct {
s string
}
So Basically what it is returning is field of string type.
fmt.Errorf
returns basically a string that is wrapped as an error. If you provide wrong arguments like in the following example, you still get an error but with the error message of the format fault inside the string message:
package main
import "fmt"
func main() {
fmt.Println(fmt.Errorf("abc", 5))
}
outputs the error string:
abc%!(EXTRA int=5)
These functions are not expected to be used in a context where you do not know the arguments that you are providing. The typical use case is that you "test" your formatting code when you write it. In your output code you will spot these error messages easily. You should just make sure to test these calls before going into production.
The danger of a panic in these functions is negligible, panics are caught as stated in the documentation:
If an Error or String method triggers a panic when called by a print routine, the fmt
package reformats the error message from the panic, decorating it with an indication
that it came through the fmt package. For example, if a String method calls
panic("bad"), the resulting formatted message will look like
%!s(PANIC=bad)
You should try to catch errors at compile and test time, not run time. For fmt.Errorf
, run go vet
.
For example,
package main
import "fmt"
func main() {
err := fmt.Errorf("%v")
fmt.Println(err)
}
Output:
$ go vet errorf.go
# command-line-arguments
./errorf.go:6: Errorf format %v reads arg #1, but call has 0 args
$
$ go run errorf.go
%!v(MISSING)
$
Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string. Vet uses heuristics that do not guarantee all reports are genuine problems, but it can find errors not caught by the compilers.
Vet is normally invoked using the go command by running "go vet":
go vet
Flag: -printf
Suspicious calls to functions in the Printf family, including any functions with these names, disregarding case:
Print Printf Println Fprint Fprintf Fprintln Sprint Sprintf Sprintln Error Errorf Fatal Fatalf Log Logf Panic Panicf Panicln
The -printfuncs flag can be used to redefine this list. If the function name ends with an 'f', the function is assumed to take a format descriptor string in the manner of fmt.Printf. If not, vet complains about arguments that look like format descriptor strings.
It also checks for errors such as using a Writer as the first argument of Printf.
Formatted output errors, by design, are a special case. For example, an error when reporting an error can be circular.
Format errors:
If an invalid argument is given for a verb, such as providing a string to %d, the generated string will contain a description of the problem, as in these examples:
Wrong type or unknown verb: %!verb(type=value) Printf("%d", hi): %!d(string=hi) Too many arguments: %!(EXTRA type=value) Printf("hi", "guys"): hi%!(EXTRA string=guys) Too few arguments: %!verb(MISSING) Printf("hi%d"): hi%!d(MISSING) Non-int for width or precision: %!(BADWIDTH) or %!(BADPREC) Printf("%*s", 4.5, "hi"): %!(BADWIDTH)hi Printf("%.*s", 4.5, "hi"): %!(BADPREC)hi Invalid or invalid use of argument index: %!(BADINDEX) Printf("%*[2]d", 7): %!d(BADINDEX) Printf("%.[2]d", 7): %!d(BADINDEX)
All errors begin with the string "%!" followed sometimes by a single character (the verb) and end with a parenthesized description.
If an Error or String method triggers a panic when called by a print routine, the fmt package reformats the error message from the panic, decorating it with an indication that it came through the fmt package. For example, if a String method calls panic("bad"), the resulting formatted message will look like
%!s(PANIC=bad)
The %!s just shows the print verb in use when the failure occurred. If the panic is caused by a nil receiver to an Error or String method, however, the output is the undecorated string, "".