Go/append
表示
< Go
appendとは
[編集]appendはGoの事前宣言された組み込み関数で、スライスに要素を追加するために使用されます。
func append(slice []Type, elems ...Type) []Type
基本的な使い方
[編集]s := []int{1, 2, 3} s = append(s, 4) // [1, 2, 3, 4] s = append(s, 5, 6, 7) // [1, 2, 3, 4, 5, 6, 7]
他のキーワード・識別子との組み合わせ
[編集]// 事前にキャパシティを指定してスライスを作成 s := make([]int, 0, 10) s = append(s, 1, 2, 3) // 長さとキャパシティを指定 s := make([]int, 5) // [0, 0, 0, 0, 0] s = append(s, 6, 7) // [0, 0, 0, 0, 0, 6, 7]
// スライスを展開して追加 s1 := []int{1, 2, 3} s2 := []int{4, 5, 6} s1 = append(s1, s2...) // [1, 2, 3, 4, 5, 6] // 文字列を[]byteに変換して追加 s := []byte("Hello") s = append(s, " World"...) // []byte("Hello World")
s := make([]int, 0, 5) fmt.Printf("len=%d cap=%d\n", len(s), cap(s)) // len=0 cap=5 s = append(s, 1, 2, 3) fmt.Printf("len=%d cap=%d\n", len(s), cap(s)) // len=3 cap=5 s = append(s, 4, 5, 6) // キャパシティを超える fmt.Printf("len=%d cap=%d\n", len(s), cap(s)) // len=6 cap=10(自動拡張)
// appendとcopyを組み合わせた効率的なスライス操作 func insertAtIndex(slice []int, index int, value int) []int { slice = append(slice, 0) copy(slice[index+1:], slice[index:]) slice[index] = value return slice } s := []int{1, 2, 4, 5} s = insertAtIndex(s, 2, 3) // [1, 2, 3, 4, 5]
var s []int // nil スライス s = append(s, 1) // [1] - nilスライスでも安全に使用可能 // nilチェックは不要 if s == nil { s = append(s, 1) // これは安全 }
func processItems() []string { var results []string defer func() { results = append(results, "cleanup completed") }() results = append(results, "processing...") return results }
// rangeでスライスを反復しながらappend source := []int{1, 2, 3, 4, 5} var evens []int for _, v := range source { if v%2 == 0 { evens = append(evens, v) } }
8. [[../interface{}|interface{}]]との組み合わせ
[編集]// 異なる型の値を格納 var mixed []interface{} mixed = append(mixed, 1, "hello", true, 3.14) // 型アサーションと組み合わせ for _, v := range mixed { switch val := v.(type) { case int: fmt.Printf("Integer: %d\n", val) case string: fmt.Printf("String: %s\n", val) } }
実用的なユースケース
[編集]1. 動的配列としての使用
[編集]func readLines() []string { var lines []string scanner := bufio.NewScanner(os.Stdin) for scanner.Scan() { lines = append(lines, scanner.Text()) } return lines }
2. フィルタリング
[編集]func filter(slice []int, predicate func(int) bool) []int { var result []int for _, v := range slice { if predicate(v) { result = append(result, v) } } return result } numbers := []int{1, 2, 3, 4, 5, 6} evens := filter(numbers, func(n int) bool { return n%2 == 0 })
3. スライスのマージ
[編集]func merge(slices ...[]int) []int { var result []int for _, slice := range slices { result = append(result, slice...) } return result } s1 := []int{1, 2} s2 := []int{3, 4} s3 := []int{5, 6} merged := merge(s1, s2, s3) // [1, 2, 3, 4, 5, 6]
4. キューの実装
[編集]type Queue struct { items []int } func (q *Queue) Enqueue(item int) { q.items = append(q.items, item) } func (q *Queue) Dequeue() int { if len(q.items) == 0 { return 0 } item := q.items[0] q.items = q.items[1:] return item }
5. 重複除去
[編集]func unique(slice []int) []int { seen := make(map[int]bool) var result []int for _, v := range slice { if !seen[v] { seen[v] = true result = append(result, v) } } return result }
6. バッファとしての使用
[編集]type Buffer struct { data []byte } func (b *Buffer) Write(p []byte) (n int, err error) { b.data = append(b.data, p...) return len(p), nil } func (b *Buffer) String() string { return string(b.data) }
パフォーマンスの考慮事項
[編集]// 悪い例:キャパシティを考慮しない func badAppend() []int { var s []int for i := 0; i < 1000; i++ { s = append(s, i) // 再割り当てが頻繁に発生 } return s } // 良い例:事前にキャパシティを設定 func goodAppend() []int { s := make([]int, 0, 1000) // キャパシティを事前設定 for i := 0; i < 1000; i++ { s = append(s, i) } return s }
注意点
[編集]- 戻り値の代入:
appendは新しいスライスを返すため、結果を元の変数に代入する必要があります - キャパシティの自動拡張: キャパシティが不足すると自動的に拡張されますが、パフォーマンスに影響します
- ポインタの共有: 容量を超えない限り、元のスライスと底層配列を共有する可能性があります
appendはGoでスライスを扱う際の中核となる関数で、動的配列やバッファ、データ処理パイプラインなど様々な場面で活用されます。