The following produces infinite recursion when Error is invoked:
var _ errors.SafeFormatter = (*MyFooError)(nil)
var _ fmt.Formatter = (*MyFooError)(nil)
// SafeFormatError implements errors.SafeFormatter.
func (e *MyFooError) SafeFormatError(p errors.Printer) error {
p.Printf("I am the error text and would like to not be duplicated")
return nil
}
// Format implements fmt.Formatter.
func (e *MyFooError) Format(s fmt.State, verb rune) { errors.FormatError(e, s, verb) }
// Error implements error.
func (e *MyFooError) Error() string {
return fmt.Sprint(e)
}
func (e *MyFooError) String() string {
return redact.Sprint(e).StripMarkers()
}
However, this seems idiomatic.
The problem appears to be that FormatError will at one point load the error mark and invoke Error(), which re-enters the machinery from the top.
There is a workaround:
func (e *MyFooError) printf(printf func(string, ...interface{})) {
printf("I am the error text")
}
func (e *MyFooError) Error() string {
var s string
e.printf(func(format string, strings ...interface{}) { s = fmt.Sprintf(format, strings...) }
return s
}
func (e *MyFooError) SafeFormatError(p errors.Printer) error {
e.printf(p.Printf)
return nil
}
The following produces infinite recursion when
Error
is invoked:However, this seems idiomatic.
The problem appears to be that
FormatError
will at one point load the error mark and invokeError()
, which re-enters the machinery from the top.There is a workaround:
but I found the behavior surprising.