Go のスライスと配列の違い
Go には配列とスライスという2つの似たデータ構造がありますが、実際の開発ではスライスを使う場面がほとんどです。両者の違いを正しく理解しておくことが重要です。
固定長と可変長
配列はサイズが型の一部であり、宣言時に決めたサイズを変更できません。一方、スライスはサイズを自由に増減できます。
配列
サイズが固定。[3]int と [5]int は別の型として扱われる。
スライス
サイズが可変。append で要素を追加でき、サイズが自動的に拡張される。
// 配列:サイズは型の一部
var arr1 [3]int
var arr2 [5]int
// arr1 = arr2 // コンパイルエラー:型が異なる
// スライス:サイズは型に含まれない
var slice1 []int
var slice2 []int
slice1 = slice2 // OK関数への渡し方
配列を関数に渡すと、値がコピーされます。一方、スライスは内部で配列への参照を持っているため、コピーは軽量で、変更が呼び出し元にも反映されます。
func modifyArray(arr [3]int) {
arr[0] = 999
}
func modifySlice(s []int) {
s[0] = 999
}
func main() {
arr := [3]int{1, 2, 3}
modifyArray(arr)
fmt.Println(arr[0]) // 1(変更されない)
slice := []int{1, 2, 3}
modifySlice(slice)
fmt.Println(slice[0]) // 999(変更される)
}配列の場合は全要素がコピーされるため、大きな配列を関数に渡すとパフォーマンスに影響します。
宣言時の構文
見た目は似ていますが、[] の中にサイズを書くかどうかで区別されます。
| 構文 | 種類 | 説明 |
|---|---|---|
| [3]int | 配列 | サイズ3の固定長配列 |
| []int | スライス | 可変長のスライス |
| [...]int{1,2,3} | 配列 | 要素数から自動推論 |
[...] 構文は配列の省略記法で、初期化時の要素数に基づいてサイズが決まります。これもスライスではなく配列です。
いつ配列を使うか
実際のコードではスライスを使うことがほとんどですが、以下のような場合には配列が適しています。
基本的には「迷ったらスライスを使う」と覚えておけば問題ありません。