new
new
はジェネリックの初期化に使用され、アドレスを返します。そのため、通常はポインタ変数を使用してnew
で初期化された型を受け取ります。特に注意すべきは、new
はゼロ値で型を初期化することです。つまり、文字列は""
、数値は0
、チャネル、関数、マップ、スライスなどはnil
になります。
この特性のため、次のようなマップへの操作を行うとpanic: assignment to entry in nil map
というエラーが発生します。
func main() {
people := new(map[string]string)
p := *people
p["name"] = "Kalan" // panic: assignment to entry in nil map
}
初期化されたマップはnilマップであり、他のプリミティブ型とは異なり、デフォルト値が存在しないことに注意してください。
struct
を使用して初期化する場合、アドレスを示すために&
を直接使用することもできます。以下の2つの方法は同じ効果があります。
type Person struct {
Name string
Age int
}
func main() {
p := &Person{}
p := new(Person)
}
利点は、上記のPerson
に自分自身の値を追加することができることですが、new
はすべてのフィールドにゼロ値を直接設定します。
make
make
はnew
とは異なり、チャネル、マップ、スライスなどの特殊な型を初期化するために使用されます。また、特筆すべきは、make
はポインタを返さないということです。ポインタを取得するには、new
のような方法で型を初期化する必要があります。
func main() {
receiver := make(chan string) // チャネルの初期化、ポインタは返されない
person := make(map[string]string)
people := make([]string, 100) // 長さ100の文字列配列の初期化
}
再度強調しますが、**make
はポインタを返しません!**次のコードはエラーになります。
func main() {
person := make(map[string]string)
fmt.Println(*person) // invalid indirect of person
}
結論
new
とmake
は、golangを初めて学ぶ際に混同しやすく、ポインタを渡す必要がある場合にも誤ってmake
を使用することがあります。この2つの違いを知ることは非常に重要です。