次のコードでは、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
これは、静的型Nexter
(単なるインターフェース)は、さまざまな値を保持できます。動的種類。
はい、*Node
を実装しているのでNexter
、p
変数5月型の値を保持します*Node
が、その他のタイプ実装も同様にNexter
、またはそれが保持する可能性がある何もないまったく(nil
価値)。そして型アサーション仕様から引用しているため、ここでは使用できません。
x.(T)
それx
はないnil
に格納されている値は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
}
または、より良い方法として、特別な「カンマOK」形式を使用します。
// This will never fail:
if n, ok := p.(*Node); ok {
fmt.Printf("n=%#v\n", n)
}
「カンマOK」形式の使用:
アサーションが成立する場合、の値は
ok
です。それ以外の場合は であり、 の値は型 のゼロ値です。true
false
n
T
この場合、ランタイムパニックは発生しません。