Golangの配列(array)とスライス(slice)

2717 ワード

huangwenwei-行間|Golangの配列(array)とスライス(slice)
日文描述约定array:配列slice:スライス
機械で次のコードを実行しないで、テストをしてください.出力を出してください.
vals :make([]int, 5)
for i:= 0; i < 5; i++ {
    vals = append(vals, i)
}
fmt.Println(vals)

もしあなたが推測した結果が[0 0 0 0 0 1 2 3 4]だったら、おめでとうございます.なぜ正解は[0 1 2 3 4]ではないのですか?ほとんどのGolang初心者はこのテスト問題を間違えます.この文章では、なぜ私たちが望んでいる出力結果ではないのか、sliceデータ型のcapacityとlengthの使い方を検討します.

Slices VS Arrays


初心者ではGolangの配列とスライスの違いがあるかもしれませんが、スライスの使用に慣れていると、コードが大幅に最適化されます.配列とスライスには多くの違いがありますが、ここでは固定配列サイズが配列宣言時の一部であり、スライスが動的なサイズを持つことができるという最大の違いを覚えています.では、実際の符号化ではどのように表現されているのでしょうか.例えばval a [10]intでは、この配列には一定の大きさ10があるが、長さを変えることはできない.len(a)を呼び出すと、長さが配列の一部であるため、10を返します.これにより、配列の長さが10を超える必要がある場合は、val b [11]intのような別の配列オブジェクトを新規作成し、配列aの値を配列bにコピーする必要があります.あるシーンでは、固定長の配列は非常に役立ちますが、通常、柔軟な配列を作成するには、「固定サイズのない配列」が必要です.最も直接的な方法は、配列を宣言するときに十分な長さを与えることです.例えば、次のようにします.
var vals [20]int
for i := 0; i < 5; i++ {
    vals[i] = i * i
}
subsetLen := 5

fmt.Println("The subset of our array has a length of:" subsetLen)

// Add a new item to our array
vals[subsetLen] = 123
subsetLen++
fmt.Print("The subset of our array has a length of:", subsetLen)

上の例では、配列を宣言するときにその長さを20に設定し、1つの変数でその長さを5に「設定」し、要素を1つ追加するとsubsetが1増加し、配列の長さが6になる.大まかに言えば、スライスの原理であり、1つの値を設定することで配列の最大長を制限し、上記の例では20である.同時にスライスは配列要素の真の長さを表す値があり、上述の例ではsubsetLenである.したがって、スライスにはcapacity capとlength lenの2つの概念がある.スライスの内部実装は配列に基づいているが、使用方法はより柔軟で、実行がより効率的である.Capはスライス中の要素個数の増加の上限を限定し,append関数により配列下層の個数上限に関心を持つ必要はない.

私たちのテスト問題に戻ります


配列とスライスの概念と相違点が分かった後,試験問題をもう一度説明する.make関数は、スライスを宣言することができ、第1のパラメータはタイプを表し、第2のパラメータはタイプの長さを表し、第3のパラメータはオプションのパラメータであり、タイプの収容上限を表す.make([]int, 5)は、長さ5のスライスを新規作成することを示し、スライスのデフォルト収容上限(capacity)と長さが一致している.しかし、append関数は、スライスが1つの要素を増加させることを示し、スライスの収容上限が同時に増加し、スライスの末尾に1つの要素が追加される.つまり、デフォルトのスライス値が[0 0 0 0 0]であるため、5番目の要素の後ろに1つの要素を追加すると、実行結果は次のようになります.
vals := make([]int, 5)  
fmt.Println("Capacity was:", cap(vals))  
for i := 0; i < 5; i++ {
    vals = append(vals, i)
    fmt.Println("Capacity is now:", cap(vals))
}
fmt.Println(vals)
// output: [0 0 0 0 0 0 1 2 3 4]

次のコードに変更すると出力は[0, 1, 2, 3, 4]
vals := make([]int, 5)  
for i := 0; i < 5; i++ {  
      vals[i] = i
}
fmt.Println(vals)

コードが簡潔ではありません.改造します.valsの長さを0に設定し、収容上限を5に設定します.
vals := make([]int, 0, 5)
for i := 0; i < 5; i++ {
    vals = appen(vals, i)
}
fmt.Println(vals)

最後に、スライスの上限が分かれば、make関数に3番目のパラメータを加えることをお勧めします.