各追加操作では、スライスに十分な容量があるかどうかがチェックされ、十分な場合、要素は元の配列に直接追加されます新しいスライスが返されます。基になる配列は変更されません。
容量が十分でない場合は、十分な容量を持つ新しい基になる配列が作成されます。前の配列の要素が最初にコピーされ、次に新しい要素がコピーされます。が最後に追加されると、新しいスライスが返されます。基になる配列が変更されます
新しい配列の容量は、ここでに 2
を掛けて定義されます。
関連するチュートリアルの推奨事項: "golang チュートリアル"
今日、Golang スライスの基礎となる構造、つまり、reflect.SliceHeader を見たところ、append の展開が正確には一致していないことがわかりました。ソースコードは以下の通りです(Go version 1.13):
// grow grows the slice s so that it can hold extra more values, allocating // more capacity if needed. It also returns the old and new slice lengths. func grow(s Value, extra int) (Value, int, int) { i0 := s.Len() i1 := i0 + extra if i1 <p>まずAppendで型を決定し、スライスするかどうかを判断し、growを呼び出して容量を拡張します l1の判定より</p><p> を作成するだけであることがわかります。しかし、容量が不十分な場合は、現在の要素 i0 が作成されたときのみであることがわかります。が 1024 未満の場合、速度が 2 倍になるのが通常です。それ以外の場合は、毎回 25% ずつしか増加しません。コードの検証は次のとおりです: </p><pre class="brush:php;toolbar:false">func main() { str := make([]int, 1023) fmt.Println(len(str), cap(str)) str = append(str, 1) fmt.Println(len(str), cap(str)) str = append(str, 1) fmt.Println(len(str), cap(str)) } 输出: 1023 1023 1024 2048 1025 2048
初期容量が 1024 に達した後は、増加するのは 25% だけです256
func main() { str := make([]int, 1024) fmt.Println(len(str), cap(str)) str = append(str, 1) fmt.Println(len(str), cap(str)) str = append(str, 1) fmt.Println(len(str), cap(str)) } 输出: 1024 1024 1025 1280 1026 1280
もちろん、ここには別の疑問があります。初期容量が 1023 の場合、それは 1023×2 ではなく、直接 1024×2 です。初期の 500 拡張をテストすると、直接 512× になります。 2. 下位レベルは動的に調整されると推測されます。常に 2 の n 乗に加算されます。現在、組み込みパッケージの下にある append の定義のみが確認されており、引き続き調査する必要があります。