type MyError struct {
errors []string
}
func (t *MyError) Error() string {
if t == nil {
fmt.Println("t ptr empty")
return ""
}
pointers := make([]string, 0, len(t.errors))
for i, r := range t.errors {
pointers[i] = r
}
sort.Strings(pointers)
return fmt.Sprintf("n error(s) decoding:\n\n%s", len(t.errors), strings.Join(pointers, ","))
}
func main() {
var err *MyError
err.Error() // expected "panic: runtime error: invalid memory address or nil pointer dereference" here
}
The variable err is nil so calling err.Error() method is expected to cause a panic "runtime error: invalid memory address or nil pointer dereference", but the method call succeeds. Why doesn't this panic?
Michael Jones explained this well (copied as answer):
In Go the function to be called by the Expression.Name() syntax is entirely determined by the type of Expression and not by the particular run-time value of that expression, including nil.
In this manner, the invocation of a method on a nil pointer of a specific type has a clear and logical meaning.
Those familiar with vtable[] implementations will find this odd at first, yet, when thinking of methods this way, it is even simpler and makes sense. Think of:
func (p *Sometype) Somemethod (firstArg int) {}
as having the literal meaning:
func SometypeSomemethod(p *Sometype, firstArg int) {}
and in this view, the body of SometypeSomemethod() is certainly free to test it's (actual) first argument (p *Sometype) for a value of nil.
Please read: https://golang.org/ref/spec#The_zero_value
When storage is allocated for a variable, either through a declaration or a call of new, or when a new value is created, either through a composite literal or a call of make, and no explicit initialization is provided, the variable or value is given a default value. Each element of such a variable or value is set to the zero value for its type: false for booleans, 0 for integers, 0.0 for floats, "" for strings, and nil for pointers, functions, interfaces, slices, channels, and maps. This initialization is done recursively, so for instance each element of an array of structs will have its fields zeroed if no value is specified.
So in your code, var err *MyError
is nil
, you can call err.Error()
is ok even err = nill
,
**
In Go, the function to be called by the Expression.Name() syntax is entirely determined by the type of Expression and not by the particular run-time value of that expression, including nil.
**
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With