Go言語のappendでスライスに要素を追加

Go言語のappendについて

Go言語では、append関数はスライスに要素を追加するために使われる非常に便利な組み込み関数です。
スライスはGoにおける動的配列の一種で、サイズが可変であり、要素を追加したり削除したりすることができます。
append関数はスライスの最後に新しい要素を追加し、新しいスライスを返します。

append関数の基本的な使い方は以下の通りです。

package main

import "fmt"

func main() {
  // 初期のスライス
  numbers := []int{1, 2, 3}

  // スライスに要素を追加
  numbers = append(numbers, 4)

  fmt.Println(numbers) // [1 2 3 4]
}

この例では、numbersという整数スライスが最初に作成されます。
append関数を使って、新しい要素4をスライスの最後に追加し、その結果を新しいスライスとしてnumbersに再代入しています。
このように、append関数は元のスライスを変更するのではなく、新しいスライスを生成して返すため、元の変数に再代入することが一般的です。

appendの仕組み

append関数の内部では、新しい要素を追加するために、スライスの容量(cap)が十分でない場合、新しい配列を作成し、既存の要素と新しい要素をその新しい配列にコピーします。
もし容量が十分であれば、既存の配列をそのまま使用して要素を追加します。

スライスの容量が不足している場合、Goランタイムは新しいスライスの容量を動的に増やします。
通常、この容量は元の容量の2倍になりますが、要件に応じて最適化されることもあります。
これにより、スライスのサイズが大きくなったり、小さくなったりする場合のパフォーマンスを効率的に管理します。

複数の要素を追加

append関数は、単一の要素だけでなく、複数の要素を追加することもできます。
次の例は、複数の要素をスライスに追加する方法を示しています。

package main

import "fmt"

func main() {
  // 初期のスライス
  numbers := []int{1, 2, 3}

  // スライスに複数の要素を追加
  numbers = append(numbers, 4, 5, 6)

  fmt.Println(numbers) // [1 2 3 4 5 6]
}

ここでは、append関数に複数の整数を渡してスライスnumbersに追加しています。
append関数は可変長引数を取るため、任意の数の要素を追加することができます。

スライスの結合

append関数は、2つのスライスを結合するためにも使用できます。
スライスを結合する場合、追加するスライスの前に...を使用して展開する必要があります。

package main

import "fmt"

func main() {
  // 初期のスライス
  numbers := []int{1, 2, 3}
  moreNumbers := []int{4, 5, 6}

  // スライスを結合
  numbers = append(numbers, moreNumbers...)

  fmt.Println(numbers) // [1 2 3 4 5 6]
}

この例では、numbersというスライスにmoreNumbersという別のスライスの要素をすべて追加しています。
...はスライスを展開し、それぞれの要素を個別にappendに渡すために必要です。

スライスのコピーと注意点

Goでは、スライスは参照型であり、基になる配列を参照します。
したがって、appendを使用すると、新しいスライスが作成される場合がありますが、元のスライスが基になる配列を参照し続けることに注意が必要です。
これにより、予期しない動作が発生する可能性があります。
たとえば、元のスライスが変更されると、新しいスライスにも影響を及ぼす可能性があります。

以下は、この挙動を示す例です。

package main

import "fmt"

func main() {
  // 初期のスライス
  original := []int{1, 2, 3}

  // 新しいスライスを作成
  newSlice := append(original, 4)

  // 元のスライスを変更
  original[0] = 100

  fmt.Println("original:", original) // original: [100 2 3]
  fmt.Println("newSlice:", newSlice) // newSlice: [1 2 3 4]
}

この例では、originalスライスが変更されると、新しいnewSliceには影響がないことが確認できます。
これは、appendが新しい配列を作成し、それに要素をコピーするためです。

まとめ

append関数はGo言語でスライスを操作する際に非常に強力で柔軟なツールです。
新しい要素の追加、スライスの結合、容量の管理など、さまざまな操作を簡単に行うことができます。
スライスの動作やメモリの管理を理解することで、より効果的にappendを使用することができます。
append関数を使いこなすことで、Goプログラムをより効率的かつ柔軟に構築できるようになります。