Collections
slice: 容量に余裕があるappendは同じ配列を書き換える
appendが必ず新しい配列を確保するとは限らず、元のsliceと配列を共有することがあります。
Sourceappend.go
Go 1.22
package sliceexample
func AppendLabel(values []string) []string {
return append(values, "third")
}Testappend_test.go
Go 1.22
package sliceexample
import "testing"
func Test容量に余裕があるsliceへのappendは同じバッキング配列を書き換える(t *testing.T) {
values := make([]string, 2, 3)
values[0], values[1] = "first", "second"
extended := AppendLabel(values)
if got := values[:cap(values)][2]; got != "third" {
t.Fatalf("backing array value = %q, want %q", got, "third")
}
if &values[0] != &extended[0] {
t.Fatal("append allocated unexpectedly")
}
}01Assertion
このテストで確認できること
- len 2 / cap 3のsliceへappendする
- 元のsliceをcapまで広げるとthirdが見える
sliceは配列そのものではなく、配列へのビューです。append後の値を独立させたい境界では、copyで明示的に複製します。
OBSERVED RESULT
before: len=2 cap=3
after: backing array[2] → third
shared first element → true