導入
Go言語でプログラミングをしていると、構造体や変数を初期化する場面に頻繁に出くわします。特に「メモリを確保して、その場所を指し示すポインタが欲しい」という状況は非常に多いものです。そんな時、Go言語が提供している組み込み関数である「new関数」を使うと、メモリの割り当てを非常にシンプルかつ安全に行うことができます。今回は、new関数の基本と、なぜこれが開発において重要なのかを解説します。
基礎知識
new関数を理解するために、まずは「ポインタ」と「ゼロ値」という2つの概念を整理しましょう。
ポインタとは、変数の値そのものではなく、その変数がメモリ上のどこに存在しているかという「アドレス(住所)」を保持するものです。
ゼロ値とは、Go言語において変数が明示的に初期化されていない場合に割り当てられる、その型ごとのデフォルト値です(intなら0、boolならfalse、構造体なら各フィールドがゼロ値の状態など)。
new関数は、指定した型に必要なメモリ領域を確保し、その領域を「ゼロ値」で満たしてから、そのメモリ領域を指す「ポインタ」を返してくれる関数です。
実装/解決策
new関数の使い方は非常に簡単です。`new(型名)`と書くだけです。例えば`new(int)`とすれば、int型のゼロ値(0)が格納されたメモリが確保され、そのアドレス(int型)が返されます。
内部的な動作としては、Goのランタイムが提供する`mallocgc`というメモリ割り当て関数が呼び出されます。これにより、開発者はメモリの解放タイミングなどを細かく意識することなく、安全にメモリを確保することができます。これは、C言語などで発生しがちなメモリリークや不正なポインタ参照といったトラブルを、言語レベルで防ぐための仕組みです。
サンプルプログラム
以下のコードをコピーして、実際に動作を確認してみてください。
package main
import “fmt”
// 構造体を定義します
type User struct {
Name string
Age int
}
func main() {
// 1. int型のメモリを確保
// pIntは int 型になります
pInt := new(int)
fmt.Printf(“ポインタの値: %v, 指し示す先の値: %d\n”, pInt, pInt)
// 2. 構造体のメモリを確保
// pUserは User 型になります
pUser := new(User)
// ゼロ値で初期化されているので、Nameは空文字、Ageは0になります
fmt.Printf(“構造体のポインタ: %v, 中身: %+v\n”, pUser, pUser)
// 値を代入してみます
pUser.Name = “Goエンジニア”
pUser.Age = 25
fmt.Printf(“更新後の値: %+v\n”, pUser)
}
応用・注意点
new関数は便利ですが、実務では「構造体の初期化には `&MyStruct{}` のようなリテラル構文が好まれる」ことも覚えておきましょう。`new`を使うと必ずゼロ値で初期化されますが、リテラル構文を使えば、最初から特定の値を設定した状態でポインタを取得できるからです。
また、new関数はスライス、マップ、チャネルの初期化には適していません。これらは`make`関数を使う必要があります。new関数を使うと、これらのデータ構造の内部ポインタがnilのままになってしまい、実行時エラーを引き起こす可能性があるため注意してください。
まずは「単純な変数のポインタをゼロ値で作りたい」という時に、ぜひnew関数を活用してみてください。

コメント