KDOC 300: スライスのcapacityは要素数が超えたときgrowsliceで伸長する
この文書のステータス
- 作成
- 2024-11-19 貴島
- レビュー
- 2024-11-22 貴島
概要
Go言語でスライスが伸長する様子をデバッガで確認する。
func main() {
// 要素数0, 容量1
s := make([]string, 0, 1)
for i := 0; i < 100; i++ {
print("for break")
s = append(s, "a")
}
}
↑このコードは要素数が0、capacityが1なのでループの2回めでcapacityの増加処理が発生するはずである。
Goのデバッガdlvを使って、見る。
$ dlv debug main.go
# 初期化処理でのgrowsliceにブレークするので、printまで飛ばす
# 組み込み関数printはコンパイル後はprintstringになっている
(dlv) b runtime.printstring
# 飛ばす
(dlv) n
# printまで飛ばした時点で仕掛ける
(dlv) b runtime.growslice
# cap1のスライスなので、ループの最初の1回は引っかからない
# ループの2回目ではgrowsliceで止まる
要素数がcapacityを超えた2回目のループでは、growsliceが呼ばれてcapacityの伸長が行われることを確認できた。
関連
抽象。
- 容量を超えた時点でだけ、拡張の処理が走る
関連。
- 補足: KDOC 188: 『Visual Guide to Slices in Go』。容量を超えたときの再割り当ての解説
- 前提: KDOC 189: Goのスライスの要素は連続して並び、capを超えると別の位置にコピーされる。スライスが裏の配列を参照し、容量を超えると新しい配列に作り直される仕組み
- 動機: KDOC 299: appendはコンパイルするとruntime.growslice()になる。growsliceが確かに呼ばれているのを確認した