Code

package main

import "fmt"

type I interface {

M()

}

type T struct {

S string

}

func (t *T) M() {

if t == nil {

fmt.Println("<nil>")

return

}

fmt.Println(t.S)

}

func main() {

var i I

nullDescribe(i)

var t *T

fmt.Printf("t == nil: %v\n", t == nil)

nullDescribe(t)

i = t

describe(i)

i.M()

describe(t)

t.M()

i = &T{"hello"}

describe(i)

i.M()

}

func describe(i I) {

fmt.Printf("(%v, %T)\n", i, i)

}

func nullDescribe(i I) {

fmt.Printf("nullDescribe: ")

if i == nil {

fmt.Printf("...nil\n")

} else {

fmt.Printf("...not nil\n")

}

}

Will return

nullDescribe: ...nil

t == nil: true

nullDescribe: ...not nil

(<nil>, *main.T)

<nil>

(<nil>, *main.T)

<nil>

(&{hello}, *main.T)

hello

Why ?

Yes, t has default value nil, but interface in nullDescribe() holds its nil value so interface is not nil.

Links

http://www.golangprograms.com/how-to-check-pointer-or-interface-is-nil.html

https://github.com/dmitryrpm/maxima-tests/blob/master/test3.go

https://yourbasic.org/golang/default-zero-value/

https://medium.com/golangspec/interfaces-in-go-part-i-4ae53a97479c pretty good explaination

https://medium.com/golangspec/interfaces-in-go-part-ii-d5057ffdb0a6