🍳

Golang makeについての備忘録

2022/10/14に公開

経緯

業務においてGolangを触る機会が増えて配列の初期化(初期値を持たない)を行う際にパフォーマンスの観点からmakeを使用すると良いとアドバイスをいただきました。

ではなぜパフォーマンスがいいのか、つまりmakeを使用すべきなのかを調べて自分なりに落とし所を見つけられたのでその備忘録としてこの文章を記したいと思います。

makeとは

golangにおいて配列(スライス)を作成する際に使用される。

特性

make(構造体、長さ、キャパシティ)で構成される。

arr := make([]uint, 3, 5)

これにより、長さが3でキャパシティが5のスライスを作成することができた。
上記を出力してみると

[0,0,0]

という配列を獲得することができる。
※もちろんキャパシティを超えるような長さのスライスを作成することはできない。

応用

ではこの配列に対して要素の追加を行なってみるとどうなるだろうか。

arr = append(arr, 5)

// 出力結果
[0,0,0,5] (キャパシティ:5)

となる。

仮にこれで要素の数がキャパシティを超えてしまった場合どうなるのか挙動を説明したいと思う。

arr = make([]uint, 3,3)
arr = append(arr, 5)

// 出力結果
[0,0,0,5] (キャパシティ: 6)

なぜキャパシティが急に6になったのか。
これに関してはmakeの使用にもある通り

これはGo言語の仕様によるもので、容量オーバーしたら基本的に2倍(1024を超える場合は1.25倍)の値を確保します。
appendするたびに一々メモリ領域を確保してコピーする手順を踏むのは効率が悪いため
このような動作になっています。

つまり毎回要素の追加があるたびにメモリを確保するのではなくて、一気に現要素の倍の数のメモリを確保することによってパフォーマンスの向上を図っているみたいです。

よくある使い方

単純に配列を初期化してforなどのループで使用したい時

arr := make([]uint, 0, 10)
for i := range 5 {
  arr = append(arr, i)
}

// 出力結果
[0,1,2,3,4]

自分はこのような使い方が多い気がするが現場によるだろう。

makeを使用する際に引数を抜かすこともできる。

arr := make([]uint, 5)

//出力結果
[0,0,0,0,0]

引数を抜かしてしまうと0埋めされてしまうので使用には注意が必要だ。

参考文献

https://qiita.com/anyanco/items/3d7dd197368cc496e955
https://note.com/shimakaze_soft/n/n83799f0dfdb7

自己紹介

https://github.com/ryuji-cre8ive
https://twitter.com/ryuji_vlog

Discussion