Go言語 - スライス
Go言語では一旦作成された配列の要素数は変更できない。スライスは配列への参照だけれども要素数の変更は可能。スライスに要素が追加されて、配列のキャパシティを超えた場合には、より大きなキャパシティを持った配列と、そのスライスが作成されて要素の値がコピーされる。
従って、二つの変数が同じスライスを参照していて、一方の要素をキャパシティ以上に増やした場合には、その変数は新しいスライスを参照することになる。
package main import "fmt" func main() { a := make([]int, 8, 8) a[7] = 9 b := a b[6] = 8 // a と b は、同じスライス。 fmt.Println(a) // -> [0 0 0 0 0 0 8 9] fmt.Println(len(a)) // -> 8 要素数 fmt.Println(cap(a)) // -> 8 キャパシティ fmt.Println(b) // -> [0 0 0 0 0 0 8 9] fmt.Println(len(b)) // -> 8 fmt.Println(cap(b)) // -> 8 // a に1要素追加 // 要素数がキャパシティを超えた為、新しい配列のスライスになる。 a = append(a, 10) // a と b は、異なるスライス a[0] = 1 fmt.Println(a) // -> [1 0 0 0 0 0 8 9 10] fmt.Println(len(a)) // -> 9 fmt.Println(cap(a)) // -> 16 fmt.Println(b) // -> [0 0 0 0 0 0 8 9] fmt.Println(len(b)) // -> 8 fmt.Println(cap(b)) // -> 8 }
スライスは参照
スライスは実体の配列への参照なので、関数の引数で渡した場合は参照がそのまま渡される。
従って関数の中でスライスの要素を変更した場合は、元のスライスも変更される。ただし要素数を変更した場合は、関数内で新しいスライスが生成されるため、元のスライスに影響を与えない。
package main import "fmt" func incInt(i *int){ *i++ // 関数外の実体を変更する場合はポインタ指定が必要 } func incSlice(lis []int, idx int){ lis[idx]++ // 元のスライスも変更される lis = append(lis, 100) // 要素を追加 fmt.Println(lis) //-> [1 3 3 100] } // 新規スライスが作成されるので // 元のスライスに影響なし func main() { var i int = 1 fmt.Println(i) //-> 1 incInt(&i) fmt.Println(i) //-> 2 s := []int{1,2,3} fmt.Println(s) //-> [1 2 3] incSlice(s, 1) fmt.Println(s) //-> [1 3 3] }