0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Go言語のnewとmakeを完全解説!違いと使い分けを徹底的に理解しよう

Posted at

はじめに

Go言語でメモリを確保する際に使われるnewmake。どちらも初学者には混同しがちですが、それぞれの役割は大きく異なります。本記事では、それぞれの機能や使い分けについて、具体例を交えて分かりやすく解説します。

newmakeの基本的な違い

new

  • 目的: メモリを割り当て、ゼロ値で初期化する。
  • 戻り値: 割り当てられたメモリへのポインタ。
  • 対象: 値型(例: int, struct など)。

newは単純にメモリを確保するだけで、複雑な初期化処理は行いません。

package main

import "fmt"

func main() {
    p := new(int)          // *int型のメモリを確保
    fmt.Println(*p)        // => 0 (ゼロ値)
    *p = 42                // 値を代入
    fmt.Println(*p)        // => 42
}

make

  • 目的: スライス、マップ、チャネルを初期化する。
  • 戻り値: 初期化されたスライス、マップ、またはチャネル(ポインタではない)。
  • 対象: 参照型(スライス、マップ、チャネル)。

makeは、これらの参照型を初期化し、利用可能な状態にします。

package main

import "fmt"

func main() {
    s := make([]int, 3)    // 長さ3のスライスを作成
    fmt.Println(s)         // => [0 0 0]
    
    m := make(map[string]int) // 空のマップを作成
    m["key"] = 100
    fmt.Println(m)         // => map[key:100]
}

使い分けのポイント

newmakeは役割が明確に分かれているため、使い分けを覚えるのは簡単です。

  1. 値型や構造体を初期化する場合newを使用
    • ポインタが必要な場面で便利。
    • structの初期化にも使えるが、通常はリテラルの方が簡潔。
   type Person struct {
       Name string
       Age  int
   }

   func main() {
       p := new(Person)       // *Person型
       fmt.Println(p.Name)    // => "" (ゼロ値)
       p.Name = "Alice"
       fmt.Println(p)         // => &{Alice 0}
   }
  1. スライス、マップ、チャネルを初期化する場合makeを使用
    • makeが必要なのはこれらの参照型だけ。
    • 初期化されていないスライス、マップ、チャネルはnilであり、操作するとパニックが発生する。
   func main() {
       var m map[string]int  // nilのマップ
       // m["key"] = 1       // パニック発生
       m = make(map[string]int)
       m["key"] = 1          // 正常に動作
       fmt.Println(m)        // => map[key:1]
   }

注意点とベストプラクティス

  1. 構造体の初期化はリテラルを優先
    newを使うよりも、構造体リテラルを使う方が読みやすく、簡潔です。
   p := &Person{Name: "Alice", Age: 30} // 推奨
  1. 参照型は必ずmakeで初期化
    特にマップやチャネルでは、makeを使わずに操作しようとするとエラーが発生します。

  2. パフォーマンスを意識した選択

    • スライスの容量を明示的に設定する場合はmakeを使うことで効率的なメモリ割り当てが可能です。

newmakeの違いをまとめる

特徴 new make
対象 値型、構造体 スライス、マップ、チャネル
戻り値 ポインタ 初期化済みのオブジェクト
初期化の深さ ゼロ値のみ 完全な初期化
主な用途 メモリ割り当てとゼロ値 参照型の初期化

おわりに

newmakeの違いを正しく理解すれば、Go言語のメモリ管理を効率的に行うことができます。本記事を参考に、それぞれの関数を適切に使い分けて、より明確で安全なコードを書いていきましょう!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?