It turns out to be nothing but a misunderstanding of what the fmt.Println() statement is actually doing. If we use a more advanced print statement then everything becomes extremely clear:
package main
import (
"fmt"
"github.com/k0kubun/pp/v3"
)
type I interface{}
type S struct{}
func main() {
var i I
var s *S
pp.Println(s, i) // (*main.S)(nil) nil
fmt.Println(s == nil, i == nil, s == i) // true true false
i = s
pp.Println(s, i) // (*main.S)(nil) (*main.S)(nil)
fmt.Println(s == nil, i == nil, s == i) // true false true
}
The author of this post has noted a convenience feature, namely that fmt.Println() tells you the state of the thing in the interface and not the state of the interface, mistaken it as a fundamental design issue and written a screed about a language issue that literally doesn't exist.Being charitable, I guess the author could actually be complaining that putting a nil pointer inside a nil interface is confusing. It is indeed confusing, but it doesn't mean there are "two types" of nil. Nil just means empty.