package main
import "fmt"
type Xer interface{}
type S struct{}
func foo() Xer {
var s *S
fmt.Println(s == nil)
return s
}
func main() {
r := foo()
fmt.Println(r == nil)
}
outputs
true
false
Surprising (to me)!
-
scompares equal tonil, then is returned. -
ris assigned to the return value. -
rdoesn’t compare equal tonil.
What’s going on?
var s *S is declared as a pointer to a value of type S.
It’s not assigned a value, so Go assigns it a pointer’s zero value: nil.
That’s why the first comparison prints true.
foo()'s return type is Xer, an interface.
So r is an interface value.
An interface value can be thought of as a (value, concrete type) tuple.
In this case: (nil, *main.S).
r's concrete type is non-nil.
That’s why the second comparison prints false.
OK, but I’m still puzzled.
Somehow the return value, or how Go thinks of it, changes in flight from foo() to main().
I wonder if this illustrates something important about… interface values? types? compilers?
I’d like to understand it better.