6

この明らかな矛盾に遭遇したとき、私はGoインターフェースについて学ぶために単純なリンクリストインターフェースを実行していました。nextTは常にnilですが、の戻り値はそうでnext()はありません。

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?
}

nilチェック(私はする必要はありません)がないnext()と、

true
false

それで私は期待される結果を得る

true
true

バグを発見したことがありますか、それとも何らかの理由でこの驚きは意図的なものですか?zipインストール(MSIなし)を使用したGoバージョン1のWindowsでの実行

4

1 に答える 1

8

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

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

Go 標準ライブラリのcontainer/listパッケージを見て、より慣用的な一般的な連結リストの実装を確認してください。Go のインターフェイス タイプの詳細な説明を含む Russ Cox による優れた記事もあります。

于 2012-06-13T22:38:23.977 に答える