Caution
お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。
配列 / スライス
配列は固定長のデータ列で、スライスは可変長のデータ列です。Goでは柔軟性の高いスライスが日常的に使われます。
構文
// 配列の宣言(固定長)
var arr [3]int
arr := [3]int{10, 20, 30}
arr := [...]int{10, 20, 30} // 要素数を自動カウント
// スライスの宣言(可変長)
var s []int
s := []int{10, 20, 30}
s := make([]int, 長さ) // ゼロ値で初期化
s := make([]int, 長さ, 容量) // 長さと容量を指定
// スライス操作
s = append(s, 値) // 末尾に要素を追加
s = append(s, 他スライス...) // スライスを結合
dst := make([]int, len(src))
copy(dst, src) // コピー
s2 := s[開始:終了] // 部分スライス
構文一覧
| 関数/操作 | 概要 |
|---|---|
| append(s, v...) | スライスに要素を追加します。容量が足りない場合は自動で拡張されます。 |
| copy(dst, src) | srcからdstへ要素をコピーします。コピーされた要素数を返します。 |
| len(s) | スライス(または配列)の現在の要素数を返します。 |
| cap(s) | スライスの容量(再割り当てなしに保持できる最大要素数)を返します。 |
| make([]T, len, cap) | 指定した型・長さ・容量のスライスを作成します。 |
| s[i:j] | インデックスiからj-1までの部分スライスを作成します。元スライスのメモリを共有します。 |
サンプルコード
package main
import "fmt"
func main() {
// 配列(固定長)
arr := [3]string{"りんご", "みかん", "ぶどう"}
fmt.Println(arr[0], len(arr)) // りんご 3
// スライス(可変長)
fruits := []string{"りんご", "みかん"}
fmt.Printf("len=%d cap=%d\n", len(fruits), cap(fruits))
// append で要素を追加
fruits = append(fruits, "ぶどう", "もも")
fmt.Println(fruits)
// スライスのコピー(独立したメモリ)
copied := make([]string, len(fruits))
copy(copied, fruits)
copied[0] = "メロン"
fmt.Println(fruits[0]) // りんご(影響なし)
fmt.Println(copied[0]) // メロン
// 部分スライス
part := fruits[1:3]
fmt.Println(part) // [みかん ぶどう]
// makeで事前に容量を確保(パフォーマンス改善)
nums := make([]int, 0, 10)
for i := 0; i < 5; i++ {
nums = append(nums, i*2)
}
fmt.Println(nums)
}
概要
配列とスライスの大きな違いは長さが型の一部かどうかです。『[3]int』と『[4]int』は別の型ですが、スライスは長さに関係なく同じ型です。実用上はほぼスライスを使います。
部分スライス(『s[1:3]』など)は元のスライスのメモリを共有します。部分スライスへの変更は元スライスにも影響するため、独立したコピーが必要な場合は必ず『copy()』を使ってください。
大量の要素を追加することが事前にわかっている場合は、『make([]T, 0, 容量)』で容量を予約しておくと、都度メモリを再割り当てするコストが抑えられてパフォーマンスが向上します。マップと同様に、スライスも参照型である点に注意してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。