Computer368520 views
中学英語812106 views
高校日本史190647 views
小学社会310694 views
いろは3014035 views
ヒストリア291495 views
高校物理160596 views
雑学1473736 views
高校生物552029 views
中学社会669043 views
Help
Tools

English

Go のスライスの操作(append・copy)

スライスに要素を追加したり、別のスライスにコピーしたりする操作は、Go のスライス操作の中でも特に頻繁に使用します。appendcopy の使い方をマスターしましょう。

append で要素を追加

append 関数は、スライスの末尾に要素を追加した新しいスライスを返します。

numbers := []int{1, 2, 3}
numbers = append(numbers, 4)
fmt.Println(numbers) // [1 2 3 4]

append は元のスライスを変更するのではなく、新しいスライスを返します。そのため、戻り値を変数に代入する必要があります。

複数の要素を一度に追加

append の第2引数以降に複数の値を渡すことで、一度に複数の要素を追加できます。

numbers := []int{1, 2, 3}
numbers = append(numbers, 4, 5, 6)
fmt.Println(numbers) // [1 2 3 4 5 6]

スライス同士を結合

... 演算子を使うと、スライス同士を結合できます。

a := []int{1, 2, 3}
b := []int{4, 5, 6}
a = append(a, b...)
fmt.Println(a) // [1 2 3 4 5 6]

b... と書くことで、スライス b の各要素を展開して append に渡しています。

容量の自動拡張

append で要素を追加する際、容量が足りなくなると Go が自動的に新しい配列を確保します。

s := make([]int, 0, 2)
fmt.Printf("len=%d cap=%d\n", len(s), cap(s)) // len=0 cap=2

s = append(s, 1, 2)
fmt.Printf("len=%d cap=%d\n", len(s), cap(s)) // len=2 cap=2

s = append(s, 3) // 容量を超える
fmt.Printf("len=%d cap=%d\n", len(s), cap(s)) // len=3 cap=4

容量が足りなくなると、通常は現在の容量の2倍程度の新しい配列が確保されます。この処理にはコストがかかるため、要素数が予測できる場合は make で十分な容量を確保しておくと効率的です。

copy でスライスをコピー

copy 関数は、スライスの要素を別のスライスにコピーします。

src := []int{1, 2, 3, 4, 5}
dst := make([]int, 3)

n := copy(dst, src)
fmt.Println(dst) // [1 2 3]
fmt.Println(n)   // 3(コピーされた要素数)

copy はコピー先とコピー元の短い方の長さ分だけコピーします。この例では dst の長さが 3 なので、3 要素がコピーされました。

copy で独立したコピーを作る

スライスを単に代入すると、背後の配列を共有してしまいます。完全に独立したコピーを作りたい場合は copy を使います。

代入(浅いコピー)

背後の配列を共有する。一方を変更すると他方にも影響する。

copy(深いコピー)

新しい配列にコピーする。元のスライスとは独立している。

original := []int{1, 2, 3}

// 浅いコピー(共有)
shallow := original
shallow[0] = 999
fmt.Println(original[0]) // 999(影響を受ける)

// 深いコピー(独立)
original = []int{1, 2, 3}
deep := make([]int, len(original))
copy(deep, original)
deep[0] = 999
fmt.Println(original[0]) // 1(影響を受けない)

意図しない変更を防ぐため、スライスを他の関数に渡す際や、長期間保持する際には copy で独立したコピーを作ることを検討してください。