2022/01/10

[golang] makeはいつ使うのか

プログラミング言語Goを読んでいる。

組み込み関数について説明があまり載っていないようだ。
説明するまでもないのか、章として説明するようなものでもないということなのか。


new と make

C++だと、new はヒープ領域にメモリを確保するものだった。コンストラクタを呼び出したりもしてくれる。
Cだと malloc()系の関数で、これもヒープ領域に確保する。
Javaはnew しかなかったっけか。覚えてない。

Goの場合、メモリを割り当てるという意味では newmake がある。
ただ、これがどうメモリを当てるかというのは new とか make とか、あるいは var とかで決定されるわけではないそうだ。

new

It's a built-in function that allocates memory, but unlike its namesakes in some other languages it does not initialize the memory, it only zeros it.

これが new の説明だ。
初期化はしないけどゼロにはするそうだ。ゼロにするのは初期化とは言わないのか?
ともかく、malloc() して memset()でゼロクリアするようなものだろう。

引数として型だけしか取らないようだ。

make

It creates slices, maps, and channels only, and it returns an initialized (not zeroed) value of type T (not *T).

さて、make は new と違って初期化はするがゼロ埋めするわけではないそうだ。
あるいは、ゼロにするとは限らないという意味だろうか。

 

そもそも、slice 変数を作ったとして、初期値を代入しないのであれば与えたいのは最初に確保しておくメモリサイズくらいしかないだろう。ゼロで埋めておいても特によいことはないと思う。 map もそうだろう。値を追加されてからが勝負(?)だ。 channel もゼロで埋めるんじゃなくて何か特殊なことをしないといけないような気がする。そういうのをひっくるめて「初期化」と呼んでいるんだろう。

そうなると、むしろ new はいつ使うんだろう。構造体か配列くらいか? 構造体も宣言時に代入で初期化できるし、複雑なものであれば New() のようなメソッドを用意する方がよいだろう(たぶんその中でも new は使わないんじゃなかろうか)。
配列のようにサイズが最初から決まっているならゼロでクリアされているというのはありがたい気がする。

 

new も make も使わずに var で宣言しただけの場合はどうなるかというと、その型における「ゼロ値」が代入されるそうだ。構造体であってもそのここの変数は「ゼロ値」で初期化されるのだろう。
「Go には未初期化の変数というものはない」ということなので、どちらかといえば new が異色なのか。でも未初期化にならないと言うことは配列であっても初期化されるはずだから、new はいらないんじゃないの・・・?

例は書いてあるのだけど、どうもピンとこない。
変数名を付けたくないけどメモリだけはほしい、みたいなときに使えるとかも書いてあった。

 

まあ、 new を使いそうになったら「new じゃなくてよいのでは?」と考えるようにしておこう。