0Pricing
Go Academy · レッスン

new()とポインターを使う場面

newによる割り当てと一般的なポインターパターン

「new()とポインターを使う場面」はCoddyKit上の無料Go Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはGo Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Go Academyコースには全4レッスンが含まれています。

組み込み関数new()

new(T)はゼロ値に初期化されたTを確保し、*Tを返します。構造体の場合、&T{}と同等です:

package main
import "fmt"

func main() {
    p := new(int)
    fmt.Println(*p)     // 0
    *p = 42
    fmt.Println(*p)     // 42

    type Point struct{ X, Y int }
    pt := new(Point)
    fmt.Println(*pt)    // {0 0}
}

newと&T{}の比較

構造体では、&T{}のほうが慣用的で、フィールドの初期化もできます。現代のGoではnewはほとんど使いません:

package main
import "fmt"

type Config struct{ Port int; Host string }

func main() {
    a := new(Config)          // zeroed
    b := &Config{Port: 8080}  // initialized
    fmt.Println(a, b)
}

ポインタを返す場合

次の場合はコンストラクターからポインタを返します:

  • 構造体が状態を持ち、呼び出し元で同じインスタンスを共有する必要がある場合
  • 構造体がポインタレシーバーのメソッドを持つ場合(インターフェースを満たすために必要です)
  • 構造体が大きく、コピーのコストが高い場合

値を返す場合

次の場合は値を返します:

  • 型が小さい場合(フィールドが数個の場合)
  • 不変の設定である場合
  • 呼び出し元が独立したコピーを受け取ることを明確にしたい場合

例: time.Timeには多くのメソッドがありますが、値として返されます。

スライスとマップ内のポインタ

コレクションにポインタを格納すると、変更を共有できます:

package main
import "fmt"

type User struct{ Name string; Score int }

func main() {
    users := []*User{{"Alice", 0}, {"Bob", 0}}
    users[0].Score = 100
    fmt.Println(users[0]) // &{Alice 100}
}

省略可能な値を表すプリミティブ型へのポインタ

*intまたは*string型のフィールドは、nilによって「未設定」を表せます。これは、omitemptyを使うJSONや、省略可能なDBカラムで役立ちます:

package main
import "fmt"

type Profile struct {
    Name string
    Age  *int // nil means not provided
}

func main() {
    p := Profile{Name: "Alice"}
    fmt.Println(p.Age == nil) // true
    age := 30
    p.Age = &age
    fmt.Println(*p.Age) // 30
}

ポインタの増やし過ぎを避ける

ポインタを過度に使うとGCへの負荷が増え、キャッシュ局所性が低下します。パフォーマンスだけを理由に値型をポインタへ変更する前に、ベンチマークを実行してください。

makeとnewの比較

makeはスライス、マップ、チャネルを初期化します(これらには内部的なセットアップが必要です)。newは任意の型をゼロ値で確保し、ポインタを返します。それぞれ目的が異なります:

package main
import "fmt"

func main() {
    s := make([]int, 5)           // usable slice
    m := make(map[string]int)     // usable map
    p := new(int)                 // *int pointing to 0
    fmt.Println(s, m, *p)
}

不変ポインタパターン

*Tを返しますが、不変であることをドキュメントに記載します。利用側では変更しないでください。これは、複数のゴルーチンで共有する設定オブジェクトでよく使われます。

ポインタの安全性に関するまとめ

ポインタを安全に扱うためのルール:

  • デリファレンスする前に必ずnilを確認します
  • スタック変数へのポインタを、その変数の有効期間を超えて保持しないでください(Goのエスケープ解析がこれを処理します)
  • 絶対に必要な場合を除き、unsafe.Pointerをキャストしないでください
  • スタックとヒープのどちらを使うかはコンパイラーに任せてください

確認問題

new(int)は何を返しますか?

まとめ: newとポインタ

重要なポイント:

  • new(T)はゼロ値の*Tを返します。ほとんど使わないため、&T{}を優先します
  • 小さい型や不変の型では値を、状態を持つ型や大きな型ではポインタを返します
  • *T型のフィールドによって、nilで「存在しない」ことを表せます
  • ポインタを使い過ぎないでください。GCにはコストがかかります

練習課題

MaxConnections用の*intフィールドを持つSettings構造体を作成してください。*Settingsを受け取り、フィールドがnilの場合にだけデフォルト値を設定する関数を作成してください。

よくある質問

「new()とポインターを使う場面」レッスンは無料ですか?

はい。「new()とポインターを使う場面」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Go Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Go Academyコースには全4レッスンが含まれています。

「new()とポインターを使う場面」で何を学びますか?

newによる割り当てと一般的なポインターパターン ブラウザで直接実行するハンズオンコードでGo Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Go Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのGo Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。

「new()とポインターを使う場面」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このGo Academyレッスンでコードを書いて実行できますか?

はい。すべてのGo Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. ポインターとは
  2. ポインターと関数
  3. メソッドのポインターレシーバー
  4. new()とポインターを使う場面
← Go Academyに戻る