NO IMAGE

【Go】つぶやきmake()

NO IMAGE

この頃担当しているシステムで、`make()`関数をよく見かけます。少し気になったので調べてみました。

Contents

make()関数


スライス(slice)、マップ(map)、チャネル(channel)といった、Goの参照型を生成するときに使う組み込み関数です。それぞれの参照型に対して2つずつ、呼び出し方が用意されています。ここではさらっと、その中身を見ていくことにします。

スライスのmake


スライスは、他の言語でいうところの「可変長配列」を表現する型です。`make(T, n)`を使うことで、要素数と容量がnであるT型のスライスを生成できます。

package mainimport "fmt"func main() {strs := make([]string, 3)fmt.Println(strs)}
$ go run main.go[  ]

また、`make(T, n, m)`を使うことで、要素数がnで容量がmであるT型のスライスをつくれます。ここで「要素数」と「容量」の関係ですが、ざっくりいうと「なかみ」と「はこ」です。たとえば要素数=「なかみ」が2で容量=「はこ」が3のスライスは生成できますが、要素数=「なかみ」が3で容量=「はこ」が2のスライスは生成できません。

func main() {strs := make([]string, 3, 2)fmt.Println(strs)}
$ go run main.go# command-line-arguments./main.go:6:14: len larger than cap in make([]string)

マップのmake


マップについては、`make(T)` でT型のマップを、`make(T, n)`でT型のマップを要素数nをヒントにして生成できます。


ここで「要素数nをヒントにして生成」とは、いわば「その要素数が入る分のメモリ領域を確保しといてね」とGoのランタイムにお願いする、というようなイメージです。たとえば、10万ほどの要素が追加されると見込まれるような時にこのmake(T, n)を使うと、パフォーマンス向上も見込める場合があります。

func main() {strs := make(map[int64]string)strs[1] = "First"strs[2] = "Second"strs[3] = "Three"// 10000要素が入るくらいのメモリを確保してもらうints := make(map[string]int32, 10000)ints["one"] = 1ints["two"] = 2ints["three"] = 3fmt.Println("make(T):", strs)fmt.Println("make(T, n):", ints)}

チャネルのmake


Go言語では「go文」を用いて、非同期に複数実行されるゴルーチンを生成できます。チャネルは、あるゴルーチンと別のゴルーチンの間でデータの受け渡しができるようデザインされた、Goに特有の型です。`make(T)`によって、「バッファ」のサイズが0のチャネルを生成できます。

チャネルのバッファ

そもそもチャネルは、「キュー(Queue, 待ち行列)」の性質を備えたデータ構造です。チャネルにおけるバッファとは、このキューを格納しておくための領域だとみなせます。先の`make(T)`は、このバッファのサイズが0のチャネルを生成する、ということです。もしバッファサイズをnだと指定するときは、`make(T, n)`が使えます。

NO IMAGE
最新情報をチェックしよう!