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