2012-06-13 4 views
5

私はこの明らかな矛盾を見つけたときに、Goインタフェースについて学ぶための簡単なリンクリストインターフェースを行っていました。 nextTは常にゼロですが、戻り値はnext()ではありません。 (私は実行する必要はありません)nilのチェックなしポインタ受信機に一貫性のないnil

package main 

import (
    "fmt" 
) 

type LinkedList interface { 
    next() LinkedList 
} 

type T struct { 
    nextT *T 
} 

func (t *T) next() LinkedList { 
    //uncomment to see the difference 
    /*if t.nextT == nil { 
     return nil 
    }*/ 
    return t.nextT//this is nil! 
} 

func main() { 
    t := new(T) 
    fmt.Println(t.nextT == nil) 

    var ll LinkedList 
    ll = t 
    fmt.Println(ll.next() == nil)//why isn't this nil? 
} 

next()で、私はそれで

true 
false 

を取得し、私が期待した結果

true 
true 

を取得するには、私が発見しましたバグか何かの理由でこの意外な意図ですか? zipインストール(MSIなし)を使用してGoバージョン1でWindows上で実行

答えて

7

いいえ、これはバグではありません。 Goのインタフェースは、基本的に2つの値のペアです。つまり、型情報と実際のデータへのポインタです。型指定されていない値nilをインタフェースに割り当てることは、インタフェースのゼロ値にもなります。これは、インタフェースに型情報も格納されているデータへのポインタもないことを意味します。

一方、インターフェイスに*Tポインタを割り当てると、それに従ってタイプ情報が設定され、データポインタがこのポインタをポイントするようになります。その場合、特定の値を持つ特定のタイプが内部に格納されているため、インターフェイスはもうnilではありません。あなたのケースでは、あなたが保存した値がゼロであることが起こります。タイプアサーション(またはreflectパッケージ)を使用して、インターフェイスに特定のタイプが割り当てられているかどうかを確認できます。タイプアサーションは、タイプ情報が一致する場合にのみ成功します(これまでは、そのインターフェイスにnilを割り当てていた場合は絶対に当てはまりません)。テストが成功すると、*Tが返されますが、このポインタの値はまだnil(そのタイプの有効な値)です。

Go標準ライブラリのcontainer/listパッケージを見て、より慣用的な一般的なリンクリストの実装を見てください。また、Goのインターフェースタイプの詳細な説明を含むRuss Coxのexcellent articleもあります。

関連する問題