🍋
Goのmake関数
make
make
関数でできることは、Slice、Map、Channel、の3つのデータ型を初期化して利用可能な状態にすること。
型Tを指定し、その後に型固有の式のリストを続ける。T型の値を返し、メモリは初期化される。
Sliceの作成
make(type, n[, m])
- type: スライスを表す型、[]T
- n: 長さ
- m: 容量
s := make([]int, 3, 5) // int型、長さ3、容量5
fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s) // len=3 cap=5 [0 0 0]
Mapの作成
make(type[, n])
- type: Mapを表す型、map[K]V
- n: 容量
m := make(map[string]int) // キーがstring型、値がint型
m["a"] = 10
m["b"] = 20
fmt.Println(m) // map[a:10 b:20]
Channelの作成
make(type[, n])
- type: Channelを表す型、chan T
- n: バッファーサイズ
ch := make(chan int, 2) // バッファサイズ2のint型
ch <- 42
fmt.Println(<-ch) // 42
new
の話
new
を使うことでもSlice等を作成することができるが、make
とは違った動きをする。
new(T)
はT型のゼロ値へのポインタを返す。Slice、Map、Channelのゼロ値はnilであるため、new(T)
で作成したポインタを通じて値を操作しようとするとエラーになってしまう。
nm := new(map[string]int) // newでMapの作成
fmt.Println(*nm) // map[]
if *nm == nil {
fmt.Println("nil!") // nil
}
(*nm)["Apple"] = 1
出力
map[]
nil!
panic: assignment to entry in nil map(以下省略)
new
で作成したMapを利用可能にするには初期化をする必要がある。
以下のコードであれば正常に動作する。
nm := new(map[string]int) // newでMapの作成
nm = &map[string]int{}
(*nm)["Apple"] = 1
fmt.Println(*nm) // map[Apple:1]
長い&ポインタ周りの変換が必要になってしまうため、基本的には make
を使うので問題ない。
参考
The Go Programming Language Specification - Built-in functions - Making slices, maps and channels
Effective Go - Data - Allocation with new
Discussion