I was going through this article by Andrew Gerrand and the author mentions that since error is an interface
you can use arbitrary data structures as error values, to allow callers to inspect the details of the error.
and gives this example
type NegativeSqrtError float64
func (f NegativeSqrtError) Error() string {
return fmt.Sprintf("math: square root of negative number %g", float64(f))
}
but didn't really show how it is implemented, only discussing its possible use in type assertions. Although I imagined you could simply just return it with a value when the situation occurs as opposed to using fmt.Errorf as shown in the example below
package main
//trying to define a custom error type in Go
import "fmt"
type NegativeError float64
func (f NegativeError) Error() string {
return fmt.Sprintf("%v: temperature can't go below absolute zero", f)
}
func compute(a, b float64) (float64, error) {
var t float64
t = a - b
if t < 0 {
return t, NegativeError(t)
}
return t, nil
}
func main() {
fmt.Println(compute(4, 5))
}
But this doesn't work and gives rise to the error below
runtime: goroutine stack exceeds 1000000000-byte limit
runtime: sp=0xc0200e13a0 stack=[0xc0200e0000, 0xc0400e0000]
fatal error: stack overflow
This seems to only be an issue when you implement the error interface's Error() method, but it works when you change the method name. (shown below)
package main
//trying to define a custom error type in Go
import "fmt"
type NegativeError float64
func (f NegativeError) Err() string {
return fmt.Sprintf("%v: temperature can't go below absolute zero", f)
}
func compute(a, b float64) (float64, string) {
var t float64
t = a - b
if t < 0 {
return t, NegativeError(t).Err()
}
return t, ""
}
func main() {
fmt.Println(compute(4, 5))
}
or when you implement the error interface on a struct type and not a float. (shown below)
package main
//trying to define a custom error type in Go
import (
"fmt"
)
type NegativeError struct {
value float64
}
func (f NegativeError) Error() string {
return fmt.Sprintf("%v: temperature can't go below absolute zero", f.value)
}
func compute(a, b float64) (float64, error) {
var t float64
t = a - b
if t < 0 {
return t, NegativeError{t}
}
return t, nil
}
func main() {
fmt.Println(compute(4, 5))
}
The obvious easy fix is to implement the interface on a struct type, but I would like to know if anyone else has experienced this particular error and how they handled it, or if this is the wrong way to go about it. Thanks.
%vto format the error, which calls theError()method again.go vet(run automatically in the playground) will warn you about doing this.