指针接收器的nil不一致(Go bug?)

Bra*_*ook 5 linked-list go

当我偶然发现这种明显的不一致时,我正在做一个简单的链表接口来了解Go接口.nextT总是零,但返回值next()不是.

package main

import (
    "fmt"
)

type LinkedList interface {
    next() LinkedList
}

type T struct {
    nextT *T
}

func (t *T) next() LinkedList {
    //uncomment to see the difference
    /*if t.nextT == nil {
         return nil
    }*/
    return t.nextT//this is nil!
}

func main() {
    t := new(T)
    fmt.Println(t.nextT == nil)

    var ll LinkedList
    ll = t
    fmt.Println(ll.next() == nil)//why isn't this nil?
}
Run Code Online (Sandbox Code Playgroud)

next()我得到的没有零检查(我不应该这样做)

true
false
Run Code Online (Sandbox Code Playgroud)

有了它,我得到了预期的结果

true
true
Run Code Online (Sandbox Code Playgroud)

我是否因为某种原因发现了一个错误或者这个意外的故意?使用zip安装在没有MSI的Go版本1的Windows上运行

tux*_*21b 7

不,那不是错误.Go中的接口基本上是一对两个值:类型信息和指向实际数据的指针.将无类型值分配nil给接口(也恰好是接口的零值)意味着接口既没有类型信息也没有指向存储的任何数据的指针.

另一方面,指定一个*T接口的指针,将相应地设置类型信息,并让数据指针指向该指针.在这种情况下,界面nil不再存在,因为您已经存储了具有特定值的特定类型.在你的情况下,你所存储的值恰好是零.您可以使用类型断言(或反射包)来检查接口是否已分配特定类型.只有在类型信息匹配时,类型断言才会成功(如果您之前已将nil分配给该接口,则显然不会出现这种情况).如果测试成功,您将*T返回,但此指针可能仍具有该值nil(该类型的有效值).

查看Go标准库中的容器/列表包,以查看更具惯用性的常规链接列表实现.还有一篇由Russ Cox 撰写优秀文章,其中包含对Go的界面类型的深入解释.