Nil isn't always nil in Go

I ran across some interesting behavior in Go today. Given this program, what would you expect to happen?

My first guess is that it would output this:

Trying &main.Owner{org:(*main.Organization)(nil), user:(*main.User)(nil)}
 => "NIL"
Trying &main.Owner{org:(*main.Organization)(0xc42000e200), user:(*main.User)(nil)}
 => "organization:group"
Trying &main.Owner{org:(*main.Organization)(nil), user:(*main.User)(0xc42000e250)}
 => "user:person"

However, that’s not what actually happens. Instead, you’d see this:

Trying &main.Owner{org:(*main.Organization)(nil), user:(*main.User)(nil)}
 => panic!! "invalid memory address or nil pointer dereference"
Trying &main.Owner{org:(*main.Organization)(0xc42000e200), user:(*main.User)(nil)}
 => "organization:group"
Trying &main.Owner{org:(*main.Organization)(nil), user:(*main.User)(0xc42000e250)}
 => panic!! "invalid memory address or nil pointer dereference"

To see why, it helps to see the output from the fmt.Printf statements that are in Owner.DatabaseString:

Trying &main.Owner{org:(*main.Organization)(nil), user:(*main.User)(nil)}
  [0] <nil>
  [1] (*main.Organization)(nil)
 => panic!! "invalid memory address or nil pointer dereference"
Trying &main.Owner{org:(*main.Organization)(0xc42000e200), user:(*main.User)(nil)}
  [0] <nil>
  [1] &main.Organization{name:"group"}
 => "organization:group"
Trying &main.Owner{org:(*main.Organization)(nil), user:(*main.User)(0xc42000e250)}
  [0] <nil>
  [1] (*main.Organization)(nil)
 => panic!! "invalid memory address or nil pointer dereference"

I think this is happening because Go interface types are really a type plus a value. The call to GetOrganization() returns a nil Organization, but not a nil DatabaseStringer.