Pointers 将nil接口转换为Golang中某物的指针?

Pointers 将nil接口转换为Golang中某物的指针?,pointers,interface,go,Pointers,Interface,Go,在以下代码段中,尝试将nil接口转换为某个对象的指针失败,并出现以下错误:接口转换:接口为nil,而不是*main.Node type Nexter interface { Next() Nexter } type Node struct { next Nexter } func (n *Node) Next() Nexter {...} func main() { var p Nexter var n *Node fmt.Println(n ==

在以下代码段中,尝试将nil接口转换为某个对象的指针失败,并出现以下错误:
接口转换:接口为nil,而不是*main.Node

type Nexter interface {
    Next() Nexter
}

type Node struct {
    next Nexter
}

func (n *Node) Next() Nexter {...}

func main() {
    var p Nexter

    var n *Node
    fmt.Println(n == nil) // will print true
    n = p.(*Node) // will fail
}
此处播放链接:

这究竟是为什么失败的呢?这完全有可能做到

n = (*Node)(nil)

,所以我想知道如何从nil接口开始实现类似的效果。

这是因为静态类型的变量
Nexter
(它只是一个接口)可能包含许多不同的动态类型的值

是的,由于
*Node
实现了
Nexter
,因此
p
变量可能会保存
*Node
类型的值,但它也可能保存实现
Nexter
的其他类型;或者它可能什么也不保存(
nil
value)。此处不能使用,因为引用规范:

x.(T)
断言
x
不是
nil
,并且
x
中存储的值属于
T
类型

但是在你的例子中,
x
nil
。如果类型断言为false,将发生运行时死机

如果将程序更改为使用以下命令初始化
p
变量:

var p Nexter = (*Node)(nil)
您的程序将运行并成功键入断言。这是因为接口值实际上以以下形式保存一对:
(值,动态类型)
,在这种情况下,
p
将不是
nil
,而是保存一对
(nil,*Node)
;有关详细信息,请参阅

如果您还希望处理接口类型的
nil
值,您可以这样显式地检查它:

if p != nil {
    n = p.(*Node) // will not fail IF p really contains a value of type *Node
}
或者更好:使用特殊的“逗号ok”形式:

使用“逗号确定”形式:

如果断言成立,
ok
的值为
true
。否则为
false
n
的值为
T
类型的零值在这种情况下不会发生运行时死机。

// This will never fail:
if n, ok := p.(*Node); ok {
    fmt.Printf("n=%#v\n", n)
}