Go インターフェイスにおける Nil スライスの特異な動作
Go では、スライスに空のスライスを意味する nil 値を割り当てることができます。ただし、インターフェイスを期待する関数に nil スライスが引数として渡されると、動作に驚くべき違いが現れます。
次の Go プレイグラウンドを考えてみましょう。
<code class="go">package main import "fmt" func main() { var i []int = nil yes(i) // output: true no(i) // output: false } func yes(thing []int) { fmt.Println(thing == nil) } func no(thing interface{}) { fmt.Println(thing == nil) }</code>
上の例では、yes と no の 2 つの関数が同じ nil スライスを引数として受け取ります。ただし、2 つの関数の出力は異なります。 yes は true を出力し、スライスが実際に nil であることを示します。いいえ、一方、 false と表示されます。
なぜこのような矛盾があるのでしょうか?答えは、Go インターフェースで nil スライスが内部的に表現される方法にあります。
インターフェース{}変数は、幅広い型を表すために使用され、型とデータ ポインタの 2 つのフィールドで構成されます。 nil スライスが、interface{} を期待する関数に渡されると、interface{} 型でラップされ、データ ポインタが nil に設定されます。
yes の場合、それは直接比較します。 nil への引数。事実上、スライス自体が nil かどうかを尋ねます。スライスは実際には空であるため、この比較は true を返します。
ただし、no 関数はインターフェースでラップされた nil スライスを受け取ります。{}この場合の比較は、スライスと nil の間だけでなく、インターフェース全体と nil の間でも行われます。{}ランタイム内では、この比較は結局、インターフェイスのデータ ポインタが nil かどうかをテストすることになります。これは、インターフェイス ラッパーがメモリを割り当てているため false です。
この動作は Go の FAQ にも記載されています。{}
「インターフェイスに渡される nil スライスに関する一般的な問題: nil スライスは nil インターフェイス値で表されるため、インターフェイス i (nil インターフェイス) の値をテストするときに if i == nil と書くと誤って成功する可能性があります。は false)。"
以上がNil スライスが Go のインターフェイスに渡されると異なる動作をするのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。