ホームページ >バックエンド開発 >Golang >Nil スライスが Go のインターフェイスに渡されると異なる動作をするのはなぜですか?

Nil スライスが Go のインターフェイスに渡されると異なる動作をするのはなぜですか?

Susan Sarandon
Susan Sarandonオリジナル
2024-11-03 05:32:02300ブラウズ

Why Does a Nil Slice Behave Differently When Passed to an Interface in Go?

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 サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。