インターフェースの型と 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 関数はインターフェイスを期待します。タイプ。 nil スライス i を指定して yes を呼び出すと、スライス自体が nil であるため、出力は true になります。ただし、nil スライスを指定して no を呼び出すと false になります。
なぜこれが起こるのかを理解するには、Go のインターフェイスの実装を詳しく調べる必要があります。内部的には、インターフェイス型は 2 つのフィールドを含む構造体として表されます。Itab は型記述子を参照し、Data は実際の値を保持します。
nil スライスを yes に渡すと、nil 値のみが返されます。が Data として渡されると、比較は事実上 nil == nil となり、これは true になります。ただし、nil スライスを no に渡すと、Go は自動的にそれをインターフェイス型にラップし、no(interface{[]int, nil}) のような結果になります。この場合、比較は、interface{[]int, nil} == nil となり、基礎となるデータが nil であっても、インターフェイスの型自体が nil ではないため、false を返します。
この動作は原因である可能性があります。インターフェイスの性質と、インターフェイスが nil 値とどのように相互作用するかについて説明します。 Go FAQ で説明されているように、nil インターフェースと nil 具象値は別個の概念です。インターフェイスタイプが nil 値を保持している場合、それはインターフェイス自体が nil であることを意味しません。したがって、nil 値を含むインターフェース型を nil と比較すると、結果は false になります。
以上がNil スライスと「nil」の比較が Go の具象型とインターフェイスで異なるのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。