Code:
package main
import (
"fmt"
"time"
)
func main() {
var my *time.Time
var any interface{}
any = my
stringer, ok := any.(fmt.Stringer)
println(ok) // "true", but I expected "false", as the receiver for time.Time.String() is (t time.Time), not (t *time.Time)
println(stringer.String()) // "panic: value method time.Time.String called using nil *Time pointer"
}
Question 1:
I don't understand when the type assertion succeeds here, as the receiver for time.Time.String() is (t time.Time), not (t *time.Time). The language specification states:
"If T is an interface type, x.(T) asserts that the dynamic type of x implements the interface T."
Does this mean that I should read "dynamic type of x" as "the actual type of x" or the "dereferenced type of x if x is a pointer"? Is there a formal definition of "dynamic type of x"? Or should I look at a different part of the spec?
Question 2:
Accepting that I get "true" on a pointer to a type that implements fmt.Stringer, how can I check that I can actually safely call stringer.String()? I.e. how can I prevent the runtime panic? Without using reflection. Please note: I do not mean checking if there is a nil pointer in x: the error is not raised by the time.String() implementation, in fact it might work fine with nil pointers were it defined using a pointer receiver. It seems the error is thrown by the runtime.
Thanks,
Markus