ホームページ > バックエンド開発 > Golang > Go スライスを再スライスすると予期しない容量値が発生するのはなぜですか?

Go スライスを再スライスすると予期しない容量値が発生するのはなぜですか?

Barbara Streisand
リリース: 2024-12-24 10:44:13
オリジナル
600 人が閲覧しました

Why Does Re-Slicing a Go Slice Result in Unexpected Capacity Values?

Golang でのスライスの再スライス

スライスの動作を理解することは、特に再スライスが関係する場合、混乱する可能性があります。このスニペットでは:

package main

import "fmt"

func main() {
    a := make([]int, 5)
    printSlice("a", a)
    b := make([]int, 0, 5)
    printSlice("b", b)
    c := b[:2]
    printSlice("c", c)
    d := c[2:5]
    printSlice("d", d)
}

func printSlice(s string, x []int) {
    fmt.Printf("%s len=%d cap=%d %v\n",
        s, len(x), cap(x), x)
}
ログイン後にコピー

出力により、予期しない結果が明らかになります:

a len=5 cap=5 [0 0 0 0 0]
b len=0 cap=5 []
c len=2 cap=5 [0 0] 
d len=3 cap=3 [0 0 0]
ログイン後にコピー

なぜ c の容量は 2 ではなく 5 なのでしょうか?これに答えるには、Golang のスライスの概念を理解する必要があります。

スライスは配列への軽量の参照です。スライスを作成するときは、範囲演算 ([:2] など) を使用して、参照される配列の開始インデックスと終了インデックスを指定します。ただし、この範囲操作では、基になる配列のコピーは作成されません。代わりに、同じ基礎となるデータを共有する新しいスライスが作成されます。

指定された例では、b は容量 5 の空のスライスです。範囲 [ の b のスライスとして c を作成すると、 :2] では、基本的に b の最初の 2 つの要素への参照を作成しています。 b の容量は 5 であるため、現在参照されている要素が 2 つだけであっても、c は最大 5 つの要素を含むように拡張できる可能性があります。これが、長さが 2 であるにもかかわらず c の容量が 5 である理由です。

さらに、範囲 [2:5] の c のスライスとして d を作成すると、事実上、共有するスライスを作成していることになります。基本データは b と同じですが、インデックス 2 から始まりインデックス 5 まで拡張されます。 b の容量は 5 であるため、d の容量は 3 になります。 (5-2).

次のプログラムは、この動作をより明確に示しています。

func main() {
    b := make([]int, 0, 5)
    c := b[:2]
    d := c[1:5] // equivalent to d := b[1:5]
    d[0] = 1
    printSlice("c", c)
    printSlice("d", d)
}
ログイン後にコピー

出力:

c len=2 cap=5 [0 1] // modifying d has modified c
d len=4 cap=4 [1 0 0 0] 
ログイン後にコピー

ご覧のとおり、d を変更すると、 c を変更し、c と d が両方とも同じ基になる配列 b.

に対するウィンドウであることを示しています。

以上がGo スライスを再スライスすると予期しない容量値が発生するのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート