将 nil 接口转换为 Golang 中某物的指针?
Convert nil interface to pointer of something in Golang?
在下面的代码片段中,尝试将 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
}
在此处播放 link:https://play.golang.org/p/2cgyfUStCI
为什么会失败?完全可以做到
n = (*Node)(nil)
,所以我想知道如何从 nil 接口开始实现类似的效果。
这是因为 static 类型 Nexter
的变量(这只是一个接口)可能包含许多不同的 dynamic类型。
是的,因为 *Node
实现了 Nexter
,您的 p
变量 可能 持有 *Node
类型的值,但是它可能包含其他类型以及实现Nexter
;或者它可能根本没有 (nil
值)。并且 Type assertion 不能在这里使用,因为从规范中引用:
x.(T)
asserts that x
is not nil
and that the value stored in x
is of type T
.
但是你的 x
是 nil
。并且如果类型断言为假,a 运行-time panic occurs.
如果您更改程序以初始化 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" 形式:
The value of ok
is true
if the assertion holds. Otherwise it is false
and the value of n
is the zero value for type T
. No run-time panic occurs in this case.
在下面的代码片段中,尝试将 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
}
在此处播放 link:https://play.golang.org/p/2cgyfUStCI
为什么会失败?完全可以做到
n = (*Node)(nil)
,所以我想知道如何从 nil 接口开始实现类似的效果。
这是因为 static 类型 Nexter
的变量(这只是一个接口)可能包含许多不同的 dynamic类型。
是的,因为 *Node
实现了 Nexter
,您的 p
变量 可能 持有 *Node
类型的值,但是它可能包含其他类型以及实现Nexter
;或者它可能根本没有 (nil
值)。并且 Type assertion 不能在这里使用,因为从规范中引用:
x.(T)
asserts thatx
is notnil
and that the value stored inx
is of typeT
.
但是你的 x
是 nil
。并且如果类型断言为假,a 运行-time panic occurs.
如果您更改程序以初始化 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" 形式:
The value of
ok
istrue
if the assertion holds. Otherwise it isfalse
and the value ofn
is the zero value for typeT
. No run-time panic occurs in this case.