Hey everyone,
Imagine writing a translation function that transforms internal errors into public API errors. In the first iteration,
you return nil
when no translation takes place. You make a simple change — returning the original error instead of
nil
— and suddenly your program behaves differently:
translate1: unsupported operation
translate2: internal not implemented
These nearly identical functions produce different results (Go Playground). What’s your guess?
type NotImplementedError struct{}
func (*NotImplementedError) Error() string {
return "internal not implemented"
}
func Translate1(err error) error {
if (err == &NotImplementedError{}) {
return errors.ErrUnsupported
}
return nil
}
func Translate2(err error) error {
if (err == &NotImplementedError{}) {
return nil
}
return err
}
func main() {
fmt.Printf("translate1: %v\n", Translate1(DoWork()))
fmt.Printf("translate2: %v\n", Translate2(DoWork()))
}
func DoWork() error {
return &NotImplementedError{}
}
I wanted to share a deep-dive blog post, “The Perils of Pointers in the Land of the Zero-Sized Type”,
along with an accompanying new static analysis tool, zerolint
:
Blog: “The Perils of Pointers in the Land of the Zero-Sized Type”
Repo: fillmore-labs.com/zerolint
I’ve found the posts “Intriguing Pointer Equality Behavior on Zero-Width Types” and “Inconsistent behavior with pointers to empty struct” here, but they are closed.
Do you have seen that issue in your own projects? Maybe you consider it a feature, not a bug?