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

Posted

技术标签:

【中文标题】将 nil 接口转换为 Golang 中的指针?【英文标题】:Convert nil interface to pointer of something in Golang? 【发布时间】:2015-07-21 15:18:33 【问题描述】:

在以下代码段中,尝试将 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 接口开始实现类似的效果。

【问题讨论】:

【参考方案1】:

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

是的,因为*Node 实现了Nexter,所以您的p 变量可能持有*Node类型的值,但它可能持有其他类型为很好的实现Nexter;或者它可能根本没有什么nil 值)。并且 Type assertion 不能在这里使用,因为引用规范:

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

但在你的情况下xnil。如果类型断言为假,会发生运行时恐慌

如果你改变你的程序来初始化你的p变量:

var p Nexter = (*Node)(nil)

您的程序将运行并且类型断言成功。这是因为一个接口值实际上持有一对(value, dynamic type),在这种情况下你的p不会是nil,而是持有一对(nil, *Node);详情见The Laws of Reflection #The representation of an interface。

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

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

或者更好:使用特殊的“comma-ok”形式:

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

使用“comma-ok”形式:

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

【讨论】:

以上是关于将 nil 接口转换为 Golang 中的指针?的主要内容,如果未能解决你的问题,请参考以下文章

在Golang中将结构指针转换为接口指针

有没有办法与golang中的任何指针对象进行比较?

golang 将接口值与#golang中的nil进行比较

如何将“字符串指针”转换为 Golang 中的字符串?

Go“一个包含nil指针的接口不是nil接口”踩坑

Golang 空指针nil的方法和数据成员