全くもって真新しい情報はないが、自分の勉強がてらのアウトプット。
最初に
- 配列はunderying arrayを参照している
- The programmers should avoid exposing the array and always keep it anonymousらしい(参考)
配列
-
配列は長さ(capacity)を持つ(初期化時に固定される)
-
ゆえに要素の追加はできない
-
配列の初期化
# 配列の初期化
a := [...]int{5, 10, 15,}
a := [3]int{5, 10, 15,}
スライス
-
スライスは配列を参照している
-
スライスは長さ(length)と容量(capacity)の両方を持っている。
- スライス内の要素を書き換えると、元のundelying arrayを書き換える事になる
- スライスに新しい要素をappendすると、元のundelying arrayを書き換え、またlenとcapの両方が拡張される
-
スライスはlenが可変長。可変長と言えどcapが限界。
The maximal capacity of the slice =
the capacity of the underlying array -
the position of the start of the slice in the array :
array : [0 0 0 0 0 0 0 0 0 0 0 0]
array : <---- capacity --->
slice : [0 0 0 0]
slice : <---- capacity --->
以上参考
- スライスの初期化
# (1)スライスの定義(len=cap=2になる)
s := []int{}
s := []int{5, 10,}
# (2)配列からスライスを定義
a := [100]int
s := a[1:4]
# スライスからスライスを定義(capの範囲ならlenをブチ抜けていい)
s2 := s[1:50]
# (3)スライスを定義する際にunderlying arrayも同時に定義(各要素の初期値はintだとゼロ)
## できるスライスのcap=len=4
slice1 := make([]int, 4)
## できるスライスのlen=2,cap=4
slice2 := make([]int, 2, 4)
参考によると、(1)の定義方法だと、容量 (cap) はいっぱいになるたびに2倍、2倍と拡張されている(筆者メモ:JavaのArrayListと同じ仕組み)。 容量の拡張時には、内部で新しいメモリ領域へのデータコピーが発生するため、頻繁な容量拡張が発生すると効率が悪い。 あらかじめ追加するおおよその要素数が分かっている場合は、(3)のmake 関数を使うことで、容量を指定したスライス生成を行える。
- 要素の追加
# 新しいスライスを返す
newSlice := append(s, 20)
その他メモ
- 配列は固定長、リストは可変長