Go言語のスライスのappend関数の使い方と応用例
生徒
「先生、Go言語のスライスって配列みたいだけど、append関数って何に使うんですか?」
先生
「append関数は、スライスに新しい要素を追加するときに使います。配列はサイズが決まっているけど、スライスは動的にサイズを変えられるんですよ。」
生徒
「なるほど。具体的にどうやって使うんですか?初心者でもわかるように教えてください!」
先生
「では、append関数の基本から応用まで、わかりやすく説明しますね!」
1. append関数とは?
Go言語のappend関数は、スライス(可変長の配列のような入れ物)に要素を足すための標準関数です。スライスには「いま入っている数」を表す長さ(length)と、「どこまで入れられるか」の容量(capacity)があり、appendは必要に応じて入れ物を広げながら新しい要素を受け止めます。
イメージは買い物カゴです。最初は小さなカゴでも、商品が増えたら店員さんが少し大きいカゴに中身ごと移してくれる感じ――あなたはただ「追加する」だけでOKです。ここで大切なのは、appendは新しいスライスを返すので、戻り値を受け取って使うのが基本だということです。
たとえば、空のリストに名前を1つ足すだけなら次のようになります(まずは雰囲気をつかみましょう)。
package main
import "fmt"
func main() {
var names []string // 空のスライスを用意
names = append(names, "太郎") // "太郎"を追加(戻り値を代入)
fmt.Println(names) // ["太郎"]
}
この段階では「スライス=増やせる入れ物」「append=足して返す」というイメージが持てれば十分です。細かな使い方や複数追加の書き方は、次のセクションで丁寧に見ていきます。
2. append関数の基本的な使い方
スライスに要素を追加するときは、次のように書きます。
numbers := []int{1, 2, 3}
numbers = append(numbers, 4) // 4を追加
fmt.Println(numbers) // [1 2 3 4]
このようにappendは、元のスライスと追加する要素を引数にとり、新しいスライスを返します。=で再代入して使うのがポイントです。
3. 複数の要素を一度に追加する方法
複数の要素をまとめて追加したいときも簡単です。
numbers := []int{1, 2}
numbers = append(numbers, 3, 4, 5)
fmt.Println(numbers) // [1 2 3 4 5]
このようにappendには複数の要素をカンマで区切って渡せます。
4. 他のスライスをまとめて追加する方法
別のスライスの要素をまとめて追加したいときは、スライスの前に...を付けます。これは「スライスの中身を全部展開して追加してね」という意味です。
a := []int{1, 2}
b := []int{3, 4, 5}
a = append(a, b...) // bの全要素をaに追加
fmt.Println(a) // [1 2 3 4 5]
5. append関数の内部で起きていること(簡単な解説)
appendはスライスの容量をチェックし、容量が足りなければ新しいメモリを確保してデータをコピーします。だから、スライスは自動的に大きくなっていくのです。
この動きは初心者には少し難しいですが、知っておくとスライスの仕組みが理解しやすくなります。
6. 実際にappendで要素を追加してみる
package main
import "fmt"
func main() {
fruits := []string{"りんご", "みかん"}
fmt.Println(fruits) // [りんご みかん]
fruits = append(fruits, "バナナ")
fmt.Println(fruits) // [りんご みかん バナナ]
moreFruits := []string{"ぶどう", "もも"}
fruits = append(fruits, moreFruits...)
fmt.Println(fruits) // [りんご みかん バナナ ぶどう もも]
}
[りんご みかん]
[りんご みかん バナナ]
[りんご みかん バナナ ぶどう もも]
7. append関数を使うときの注意点
- 必ず戻り値を受け取ること:
appendは新しいスライスを返すので、代入を忘れると元のスライスは変わりません。 - 元のスライスの容量を超えると新しい配列が作られるので、メモリやパフォーマンスに注意が必要な場面もあります。
- スライスの参照特性:appendで新しいスライスが作られることがあるため、複数の変数が同じスライスを参照している場合は挙動に注意してください。
8. 応用例:ユーザー入力でスライスに値を追加する
実際のプログラムでは、ユーザーからの入力を受け取ってスライスに追加することがあります。簡単な例を見てみましょう。
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
var words []string
fmt.Println("好きな言葉を入力してください。終了するにはexitと入力します。")
for {
fmt.Print("> ")
if !scanner.Scan() {
break
}
input := strings.TrimSpace(scanner.Text())
if input == "exit" {
break
}
words = append(words, input)
fmt.Println("現在のリスト:", words)
}
fmt.Println("入力を終了しました。最終リスト:", words)
}
このプログラムでは、ユーザーが入力した言葉をどんどんスライスに追加していきます。exitと入力すると終了します。
まとめ
今回はGo言語のスライス操作におけるappend関数の基本から応用まで、具体的な使い方や注意点、ユーザー入力との組み合わせまで幅広く学びました。appendは、配列のような固定長の制限を超えて、柔軟にデータを扱うための非常に重要な機能です。
特に初心者にとってありがちなミスとして、「戻り値を再代入しない」「容量と参照の違いを理解しない」という点がありますが、本記事の中で紹介した小さなサンプルを使えば、それらも自然に体験しながら理解できます。また、...(ドット3つ)を使ったスライス展開の使い方や、bufio.Scannerを使ってユーザー入力を扱う応用例も合わせて覚えておくと、日常的なプログラムでも即戦力になるでしょう。
Go言語はシンプルで高速な構文が特徴ですが、そのぶん一つ一つの動きが明確であり、理解が深まるほどコードの質も上がります。今回学んだappend関数の性質を押さえておくだけで、データ構造の扱いに関する柔軟さと堅牢さがぐっと増します。
append関数で複数のユーザー入力をまとめて処理するサンプル
たとえば、ユーザーが好きな動物を入力して、最後に一覧表示するプログラムを考えてみましょう。
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func main() {
var animals []string
scanner := bufio.NewScanner(os.Stdin)
fmt.Println("好きな動物を入力してください(終了は end):")
for {
fmt.Print("> ")
if !scanner.Scan() {
break
}
input := strings.TrimSpace(scanner.Text())
if input == "end" {
break
}
if input != "" {
animals = append(animals, input)
}
}
fmt.Println("入力された動物リスト:")
for i, a := range animals {
fmt.Printf("%d: %s\n", i+1, a)
}
}
上記のように、Go言語のappendは日常的なユーザー操作と組み合わせることで、非常に実用的なデータ収集ツールにもなります。
生徒
「appendってただ足すだけかと思ってたけど、実は戻り値をちゃんと受け取らないといけないんですね!」
先生
「その通り!appendは新しいスライスを返す仕組みだから、変数に再代入しないと追加された結果が反映されないんだ。」
生徒
「あと、容量が足りないと新しいメモリに引っ越すっていうのも、最初は気付きにくかったです。」
先生
「そこも重要なポイントだね。特に複数のスライス変数を扱うときは、参照の共有やコピーにも注意が必要になるよ。」
生徒
「append(...b)みたいに他のスライスを展開して渡せるのも便利でした。今度、入力した値をまとめて処理するときに使ってみます!」
先生
「いい心がけだね。appendの使い方をしっかり理解しておけば、Go言語のスライス操作は怖くないよ!」