将 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
类型。
但在你的情况下x
是nil
。如果类型断言为假,会发生运行时恐慌。
如果你改变你的程序来初始化你的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
。否则为false
,n
的值是T
类型的零值。 在这种情况下不会发生运行时恐慌。
【讨论】:
以上是关于将 nil 接口转换为 Golang 中的指针?的主要内容,如果未能解决你的问题,请参考以下文章