小编典典

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

go

在以下代码段中,尝试将nil接口转换为某物的指针失败,并出现以下错误: interface conversion: interface is nil, not *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
}

在此处播放链接:https :
//play.golang.org/p/2cgyfUStCI

为什么这会完全失败?完全有可能做

n = (*Node)(nil)

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


阅读 350

收藏
2020-07-02

共1个答案

小编典典

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

是的,因为*Node工具Nexter,您的p变量 可能 持有类型的值*Node,但它可以容纳 其他类型 以及其实施Nexter;
或者它可能持有 什么
都(nil值)。而且类型断言不能在这里使用,因为引用了规范:

x.(T)断言xnil和存储在值x是类型的T

但是x你的情况是nil。如果类型断言为假, 则会发生运行时恐慌

如果您更改程序以使用以下方法初始化p变量:

var p Nexter = (*Node)(nil)

您的程序将运行,并且类型声明成功。这是因为接口值实际上以以下形式持有一对:(value, dynamic type),在这种情况下,您p将不是nil,但将持有一对(nil, *Node);有关详细信息,请参见反射定律#接口的表示

如果您还想处理nil接口类型的值,则可以像下面这样显式检查它:

if p != nil {
    n = p.(*Node) // will not fail IF p really contains a value of type *Node
}

或者更好:使用特殊的“逗号分隔”形式:

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

使用“逗号分隔”形式:

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

2020-07-02