ホームページ >バックエンド開発 >Golang >Go 言語の nil スライス、非 nil スライス、空のスライス

Go 言語の nil スライス、非 nil スライス、空のスライス

WBOY
WBOY転載
2024-02-08 21:18:081282ブラウズ

Go 语言中 nil 切片、非 nil 切片、空切片

php エディタ Xiaoxin は、Go 言語のスライス タイプの概要を提供します。 Go 言語では、スライスには nil スライス、非 nil スライス、空のスライスの 3 つの状態があります。これら 3 つのスライス状態は、使用される際に異なる意味と特性を持ちます。これらのスライス タイプの違いを理解することは、Go 言語のスライス関数をよりよく理解し、使用するのに役立ちます。次に、これら 3 つのスライス タイプの具体的な機能と用途を見てみましょう。

質問内容

Goプログラミングは初めてです。 Go プログラミングの本で読んだのですが、スライスは配列へのポインター、長さ、容量の 3 つの部分で構成されています。

次の点で混乱しています:

  • nil スライス (スライスは基礎となる配列を指しません、len = 0、cap=0)
  • len = 0、cap = 0の非ゼロスライスのみ
  • 空のスライス。

nil と空のスライスが同じものであるかどうか誰か教えてください。 両方が異なる場合、これら 2 つの違いは何なのか教えてください。スライスが空かどうかをテストするにはどうすればよいですか?また、長さと容量がゼロの非ゼロスライスでは、ポインタはどのような値を保持しますか?

ソリューション

観察可能な動作

nil は空のスライス (容量 0) と同じではありませんが、観察可能な動作は (ほぼ常に) 同じです。つまり:###

スライスと 2 つの非

nil 空スライス): リーリー 出力 (Go Playground

で試してください):

リーリー (nil

スライスをスライスすると

nil スライスが生成され、非 nil スライスをスライスすると非 nil## が生成されることに注意してください。 # スライス。) ### スライス値を事前に宣言された識別子 nil と比較することによってのみ違いを見分けることができるという例外を除いて、他の点ではすべて同じように動作します。 ただし、多くのパッケージはスライスを

nil

と比較し、それに基づいて異なる処理を行う可能性があることに注意してください (例: encoding/json および fmt パッケージ)。 唯一の違いは、スライスを配列ポインタ に変換することです (Go 1.17 で言語に追加されました)。非

nil

スライスを配列ポインターに変換すると、非 nil ポインターが生成され、nil スライスを配列ポインターに変換すると、nil が生成されます。 ポインタ。 スライスが空かどうかを判断するには、単純にその長さを 0: len(s) == 0 と比較します。

nil

スライスであっても、非 nil スライスであっても、正の容量があるかどうかは関係ありません。要素がない場合は空です。 リーリー 印刷 (Go Playground で試してください): リーリー ###底### スライス値は、

reflect.SliceHeader:

で定義された構造体によって表されます。 リーリー

nil

スライスの場合、構造体の値はゼロになります。つまり、そのすべてのフィールドは値がゼロになります (つまり、0)。

nil

スライスの容量と長さが 0Len、および

Cap

フィールドと等しい場合、おそらく 0 ですが、Data ポインターはそうでない可能性があります。 ではありません 、それが nil スライスとの違いです。これは、サイズがゼロの基になる配列を指します。 Go 仕様では、サイズ 0 の異なる型の値が同じメモリ アドレスを持つことが許可されていることに注意してください。 仕様: システムノート: サイズと配置の保証:

让我们检查一下。为此,我们调用 unsafe 包的帮助,并“获取” reflect.SliceHeader 结构“视图” “我们的切片值:

var s1 []int
s2 := []int{}
s3 := make([]int, 0)

fmt.Printf("s1 (addr: %p): %+8v\n",
    &s1, *(*reflect.SliceHeader)(unsafe.Pointer(&s1)))
fmt.Printf("s2 (addr: %p): %+8v\n",
    &s2, *(*reflect.SliceHeader)(unsafe.Pointer(&s2)))
fmt.Printf("s3 (addr: %p): %+8v\n",
    &s3, *(*reflect.SliceHeader)(unsafe.Pointer(&s3)))

输出(在 Go Playground 上尝试一下):

s1 (addr: 0x1040a130): {Data:       0 Len:       0 Cap:       0}
s2 (addr: 0x1040a140): {Data: 1535812 Len:       0 Cap:       0}
s3 (addr: 0x1040a150): {Data: 1535812 Len:       0 Cap:       0}

我们看到了什么?

  • 所有切片(切片头)都有不同的内存地址
  • nil 切片具有 0 数据指针
  • s2s3 切片确实具有相同的数据指针,共享/指向相同的 0 大小的内存值

以上がGo 言語の nil スライス、非 nil スライス、空のスライスの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はstackoverflow.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。