Goにおけるmakeとnewの選択
Daniel Hayes
Full-Stack Engineer · Leapcell

Go言語は、makeとnewという2つの一般的なメモリ割り当て方法を提供しています。どちらもメモリ割り当てに使用されますが、その役割と使用場面は大きく異なります。これら2つの違いを理解することは、効率的で保守性の高いGoコードを書く上で非常に重要です。この記事では、makeとnewの違い、適切なシナリオ、およびいくつかの使用上のヒントについて徹底的に分析します。
makeとnewの基本的な違い
new: ポインタ型のゼロ値を生成
newは、Goにおけるメモリ割り当てに使用されるキーワードです。その機能は、型のためのメモリブロックを割り当て、そのメモリへのポインタを返すことです。newによって割り当てられたメモリは、その型のゼロ値に初期化されます。
例: newの使用
package main import "fmt" func main() { var p *int = new(int) fmt.Println(*p) // 出力: 0, `new`によってint用に割り当てられたメモリはゼロ値に初期化される }
- 戻り値の型:
newは型へのポインタを返します。 - ゼロ値初期化:
newは割り当てられたメモリをその型のゼロ値に初期化します。たとえば、int型の場合、ゼロ値は0、string型の場合、空文字列""です。
make: スライス、マップ、チャネルを初期化
makeは、Goの特別な組み込み関数であり、特にスライス、マップ、チャネルの3つの組み込みデータ型を初期化するために使用されます。newとは異なり、makeは割り当てられたメモリへのポインタを返さず、初期化されたオブジェクト自体を返します。
例: makeの使用
package main import "fmt" func main() { // スライスの初期化 s := make([]int, 5) fmt.Println(s) // 出力: [0 0 0 0 0] // マップの初期化 m := make(map[string]int) m["age"] = 30 fmt.Println(m) // 出力: map[age:30] // チャネルの初期化 ch := make(chan int, 2) ch <- 1 fmt.Println(<-ch) // 出力: 1 }
- 戻り値の型:
makeはポインタではなく、オブジェクト自体(スライス、マップ、またはチャネル)を返します。 - メモリ割り当てと初期化:
makeはメモリを割り当てるだけでなく、データ構造自体も初期化します。たとえば、スライスを初期化する場合、makeは基になる配列を割り当て、その長さと容量を設定します。
主な違いのまとめ
-
目的:
new: メモリを割り当て、型へのポインタを返します。make: スライス、マップ、またはチャネルオブジェクトを初期化して返します。
-
戻り値:
new: 型へのポインタを返します。make: 初期化されたオブジェクト自体を返します。
-
適用可能な型:
new: すべての型。make: スライス、マップ、チャネル。
-
初期化:
new: ゼロ値を返します。make: データ構造の型に応じて初期化します。
makeとnewの使用上のヒント
newの使用上のヒント
構造体型に適しています:
newは、構造体のメモリを割り当て、それへのポインタを返すためによく使用されます。構造体ポインタの初期値は、構造体のゼロ値であることに注意することが重要です。
例: newを使用して構造体のメモリを割り当てる
type Person struct { Name string Age int } func main() { p := new(Person) fmt.Println(p) // 出力: &{ 0} fmt.Println(p.Name) // 出力: 空文字列 fmt.Println(p.Age) // 出力: 0 }
newによって作成されたポインタ:newは構造体へのポインタを返すため、p.Nameまたはp.Ageでそのフィールドを直接変更できます。
makeの使用上のヒント
指定された容量でスライスを初期化する:
makeを使用して、指定された長さと容量でスライスを初期化できます。makeを使用すると、基になる配列を効率的に割り当ててスライスを初期化できます。
例: makeを使用して容量を持つスライスを初期化する
// 長さ5、容量10のスライスを初期化 s := make([]int, 5, 10) fmt.Println(len(s), cap(s)) // 出力: 5 10
- 初期化中にマップの容量を指定する:
makeでマップを作成するときに、その初期容量を指定できます。これにより、要素が挿入される際の複数のメモリ拡張を回避することでパフォーマンスを最適化できます。
例: makeを使用してマップを初期化する
m := make(map[string]int, 10) // 初期容量を10に設定 m["age"] = 30 m["height"] = 175 fmt.Println(m) // 出力: map[age:30 height:175]
- バッファ付きチャネルを初期化する:
makeを使用してバッファ付きチャネルを作成し、チャネルのバッファサイズを指定します。これは同時実行プログラミングで非常に役立ちます。
例: makeを使用してバッファ付きチャネルを作成する
ch := make(chan int, 2) ch <- 1 ch <- 2 fmt.Println(<-ch) // 出力: 1
適切なメモリ割り当て方法の選択
- 構造体の使用シナリオ: 構造体へのポインタのみが必要で、初期化中に特別な要件がない場合は、
newを使用するのが簡単で一般的なアプローチです。 - スライス、マップ、チャネルの使用シナリオ: スライス、マップ、チャネルを初期化する必要があり、その内容を変更する可能性がある場合は、
makeがより適切な選択です。特に、事前に容量を指定する必要がある場合はそうです。
makeとnewのパフォーマンスに関する考慮事項
- メモリ割り当てのオーバーヘッド: スライス、マップ、チャネルを初期化する場合、
makeはメモリを割り当てるだけでなく、型の初期化も実行するため、追加のオーバーヘッドが発生する可能性があります。対照的に、newはメモリを割り当てるだけでゼロ値に初期化するため、そのオーバーヘッドは比較的小さくなります。 - 不要なメモリ割り当ての回避: スライス、マップ、チャネルなどの型の場合、
makeを使用するときに適切な容量を指定して、メモリの再割り当て回数を減らすことをお勧めします。
よくある誤用
- スライスまたはマップを作成するために
newを誤って使用する:newがスライス、マップ、またはチャネルで使用される場合、その型のゼロ値のみを返し、初期化は実行しません。したがって、newを使用してスライス、マップ、またはチャネルを作成し、その内容に直接アクセスしようとすると、ランタイムエラーが発生します。
不正な例: newを誤って使用してマップを作成する
m := new(map[string]int) // 不正: ポインタを返し、初期化されたマップは返さない m["age"] = 30 // ランタイムエラー: mはnilです
正しい例: makeを使用してマップを初期化する必要があります。
m := make(map[string]int) m["age"] = 30
まとめ
Goでは、makeとnewはどちらもメモリ割り当てのためのキーワードであり、その機能は似ていますが、明確な違いがあります。
newは型のメモリを割り当てるために使用され、ポインタを返し、ほとんどの型に適しています。
一方、makeは主にスライス、マップ、チャネルを初期化するために使用され、より強力な初期化機能を提供します。
new: 構造体型やその他の基本型へのポインタの作成に適しており、メモリをゼロ値に初期化します。make: スライス、マップ、チャネルの初期化に使用され、容量の指定をサポートし、内部初期化を完了します。
これら2つの異なる使用シナリオとパフォーマンスへの影響を理解することは、より効率的で保守性の高いGoコードを作成するのに役立ちます。
Leapcellは、Goプロジェクトをホストするための最適な選択肢です。
Leapcellは、Webホスティング、非同期タスク、およびRedisのための次世代サーバーレスプラットフォームです。
多言語サポート
- Node.js、Python、Go、またはRustで開発します。
無制限のプロジェクトを無料でデプロイ
- 使用量に対してのみ支払い - リクエストも料金もかかりません。
圧倒的なコスト効率
- アイドル料金なしの従量課金制。
- 例:25ドルで、平均応答時間60ミリ秒で694万リクエストをサポートします。
合理化された開発者エクスペリエンス
- 簡単なセットアップのための直感的なUI。
- 完全に自動化されたCI/CDパイプラインとGitOps統合。
- 実用的な洞察のためのリアルタイムのメトリックとログ。
簡単なスケーラビリティと高いパフォーマンス
- 高い同時実行性を簡単に処理するための自動スケーリング。
- 運用オーバーヘッドゼロ - 構築に集中するだけです。
ドキュメントで詳細をご覧ください!
Xでフォローしてください:@LeapcellHQ



