array
長さがポイント
- 固定長配列
- 初期値は0
書き方
[長さ]型{値}
var a1 [5]int // array型の変数を宣言するとき(初期値0が入る)
var a2 = [5]int{1, 2, 3} // 配列を作って初期値を指定するとき
a3 := [5]int{1, 2, 3} // 代入演算子を使って簡易表記するとき
a4 := [...]int{1, 2, 3} // 長さを省略するとき
fmt.Println(a1, len(a1)) // [0 0 0 0 0] 5
fmt.Println(a2, len(a2)) // [1 2 3 0 0] 5
fmt.Println(a3, len(a3)) // [1 2 3 0 0] 5
fmt.Println(a4, len(a4)) // [1 2 3] 3
a1[2] = 5 // 値を変更するとき
fmt.Println(a1) // [0 0 5 0 0]
slice
ポインタと容量がポイント
- 可変長配列のようなもの
- 初期値はnil
arrayと比較して以下の違いがある。
- 実体(array)とポインタの両方を持っている
- ポインタ: エイリアスのようなもので、アドレスとも呼ばれる
- 容量(cap)を持っている
- 長さ < 容量 < 参照元の容量 の範囲内で指定できる
- スライスをスライスするときは[]の三番目に指定できる
書き方
[]型{値}
var s1 []int // slice型の変数を宣言するとき(初期値nilが入る)
var s2 = []int{1, 2, 3, 4} // 値を指定するとき
s3 := []int{1, 2, 3, 4} // 代入演算子を使って簡易表記するとき
fmt.Println(s1, len(s1), cap(s1)) // [] 0 0
fmt.Println(s2, len(s2), cap(s2)) // [1 2 3 4] 4 4
fmt.Println(s3, len(s3), cap(s3)) // [1 2 3 4] 4 4
s3s := s3[0:2] // sliceをsliceするとき
fmt.Println(s3s, len(s3s), cap(s3s)) // [1 2] 2 4(容量を指定しないと参照元を引き継ぐ)
s3sc := s3[0:2:3] // 容量を指定してsliceをsliceするとき
fmt.Println(s3sc, len(s3sc), cap(s3sc)) // [1 2] 2 3
組み込み関数make()を使う場合
- 長さと容量を指定し、sliceをつくる
- 長さは省略できないが、容量は省略できる
- 容量を省略すると、要素数=容量となる
- 初期値は0
- make関数はスライスを初期化する。初期値としてnilではなく0を格納する
書き方 : make(型, 要素数, 容量)
var sm1 = make([]int, 5) // 容量を省略してsliceをつくるとき(初期値0が入る)
var sm2 = make([]int, 5, 10) // 容量を指定してsliceをつくるとき
sm3 := make([]int, 5, 10) // 代入演算子を使って簡易表記するとき
fmt.Println(sm1, len(sm1), cap(sm1)) // [0 0 0 0 0] 5 5
fmt.Println(sm2, len(sm2), cap(sm2)) // [0 0 0 0 0] 5 10
fmt.Println(sm3, len(sm3), cap(sm3)) // [0 0 0 0 0] 5 10
組み込み関数make()は参照型にしか使えない。(slice, map, channel)
map
キーがポイント
- 連想配列のようなもの(辞書・ハッシュetc.)
- 初期値は nil
arrayやsliceと比較して以下の違いがある。
- 実体(array)を持っていない
- 組み込み関数cap()は使えない
書き方
map[キー]型
var m1 map[int]string // map型の変数を宣言するとき(初期値0が入る)
var m2 = map[string]int{ // 値を指定するとき
"dora": 0,
"nobi": 1,
}
m3 := map[string]int{ // 代入演算子を使って簡易表記するとき
"shizu": 0,
"jai": 1,
"sune": 2,
}
fmt.Println(m1, len(m1)) // map[] 0
fmt.Println(m2, len(m2)) // map[dora:0 nobi:1] 2
fmt.Println(m3, len(m3)) // map[shizu:0 jai:1 sune:2] 3
m3["deki"] = 3 // 要素を追加するとき
// m3[1:"dora"]
fmt.Println(m3, len(m3)) // map[shizu:0 jai:1 sune:2 deki:3] 4
m3["shizu"] = 100 // キーをもとに値を書き換えるとき
fmt.Println(m3, len(m3)) // map[shizu:100 jai:1 sune:2 deki:3] 4
組み込み関数make()を使う場合
- 容量を指定し、mapをつくる
- 容量は省略できる
- 初期値は0
書き方
make(map[キーの型]要素型, 容量)
var mm1 = make(map[int]int) // 容量を省略してmapをつくるとき(初期値0が入る)
var mm2 = make(map[int]string, 5) // 容量を指定してmapをつくるとき
mm3 := make(map[int]int, 5) // 代入演算子を使って簡易表記するとき
fmt.Println(mm1, len(mm1)) // map[] 0
fmt.Println(mm2, len(mm2)) // map[] 0
fmt.Println(mm3, len(mm3)) // map[] 0
var mm4 = make(map[string]string, 4) // 値を指定するとき(makeを使う場合、代入する形になる)
mm4["鳥"] = "bird"
mm4["木"] = "tree"
fmt.Println(mm4, len(mm4)) // map[鳥:bird 木:tree] 2
参考:
Go言語: いろいろなマップの作り方まとめ-Qiita
Tips
- Goでは初期値を「ゼロ値」と呼ぶ
- 「型」と「リテラル」は別物
ex) var a int = 0x0719BEEFの場合
型: int
リテラル: 10x0719BEEF(値)を指す場合とvar a int = 0x0719BEEF(表記そのもの)を指す場合がある
組み込み関数make()とnew()の違い
- make()は実体(array)をつくる。実体を返す。もともと実体を持っていない参照型にのみ使える。
- new()はメモリを割り当てるだけで、実体はつくらない。ポインタを返す。一般的に構造体型のメモリ割り当てにおいて使われる