Goのガベージコレクション
CoddyのGOジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 23/107。
CやC++などの言語とは異なり、Goはガベージコレクション(GC)によってメモリ管理を自動的に行います。使い終わったメモリを手動で解放する必要はありません。Goランタイムは、まだ使用中のメモリを追跡し、残りを再利用します。
new()、make()を使用してメモリを割り当てたり、変数を作成したりすると、Goのガベージコレクターがこれらの割り当てを監視します。値がプログラムのどの部分からも到達できなくなると、GCはそのメモリを自動的に解放します。
func createPerson() *Person {
p := &Person{Name: "Alice", Age: 30}
return p // p はヒープにエスケープし、GC が管理します
}
func main() {
person := createPerson()
fmt.Println(person.Name)
// person が使用されなくなったとき、GC がメモリを回収します
}この例では、Person 構造体は関数から返されるため、ヒープ上に割り当てられます。Go のコンパイラはエスケープ解析を実行して、変数をスタック上に保持できるか、ヒープに移す必要があるかを判断します。ガベージコレクターはヒープメモリのみを管理します。
この自動 memory 管理により、忘れられた解放による memory リークを心配せずに、アプリケーションの構築に集中できます。ただし、GC が存在することを理解しておくと、パフォーマンスが重要な場合に不要な割り当てを最小限に抑え、より効率的なコードを書くのに役立ちます。
チャレンジ
簡単Goのガベージコレクターがヒープに逃避するオブジェクトのメモリをどのように扱うかを示すセッションマネージャーを構築しましょう。動的に割り当てられて関数から返されるセッションを作成し、GCにそのライフサイクルを管理させます。
コードを2つのファイルに分けて整理します。
session.go:ID(string)、Username(string)、Data(文字列のスライス)fieldsを持つSessionstructをDefineします。IDとusernameを受け取り、ヒープ上に新しいSessionを割り当て(pointerを返すことで)、Dataスライスをemptyとして初期化するNewSessionfunctionをCreateします。また、pointer receiverを持ち、文字列をsessionのDataスライスにappendsするAddDatamethodと、sessionのdetailsを示すformatted stringを返すSummarymethodも追加します。main.go: inputからsession informationを読み取り、constructor functionを使用してsessionをCreateし、いくつかのdata entriesを追加して、session summaryを表示します。sessionはfunction内でCreateされてpointerとして返されるため、heapにescapeし、そこでgarbage collectorが管理します。
次のinputが提供されます。
- 1行目: Session ID
- 2行目: Username
- 3行目: 追加する最初のdata entry
- 4行目: 追加する2番目のdata entry
あなたのSummary methodは、次のformatのstringを返す必要があります。
Session [ID] for user [Username]
Data entries: [count]
- [entry1]
- [entry2]たとえば、sess-001、alice、login、view_dashboardが与えられた場合、outputは次のようになります。
Session sess-001 for user alice
Data entries: 2
- login
- view_dashboardここでの重要なポイントは、NewSession functionがSessionをCreateし、それへのpointerを返すことです。これにより、Sessionはstack上に留まるのではなく、ヒープに"escape"します。そのため、Sessionへの参照がなくなるとgarbage collectionの対象になります。このmemoryを手動でfreeする必要はありません。Goがautomatically処理します。
自分で試してみよう
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// セッションIDを読み取る
sessionID, _ := reader.ReadString('\n')
sessionID = sessionID[:len(sessionID)-1]
// ユーザー名を読み取る
username, _ := reader.ReadString('\n')
username = username[:len(username)-1]
// 最初のデータエントリを読み取る
data1, _ := reader.ReadString('\n')
data1 = data1[:len(data1)-1]
// 2番目のデータエントリを読み取る
data2, _ := reader.ReadString('\n')
data2 = data2[:len(data2)-1]
// TODO: NewSession関数を使用して新しいセッションを作成する
// ポインタを返すため、セッションはヒープにエスケープする
// TODO: AddDataメソッドを使用してデータエントリをセッションに追加する
// TODO: Summaryメソッドを使用してセッションの概要を出力する
fmt.Println("")
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
1Go オブジェクト指向の基礎
外部ファイルGo ワークスペースとモジュールパッケージとインポート公開された名前と非公開の名前Go におけるオブジェクト指向入門クラスとしての構造体構造体へのメソッド定義ポインタレシーバと値レシーバ構造体の初期化コンストラクタ関数まとめ:簡易計算機8エラー処理とOOP
error インターフェースカスタムエラー型エラーラッピング (fmt.Errorf)センチネルエラーerrors.Is() と errors.As()Panic、Defer、Recover復習 - ファイルパーサー自分で練習してみよう: Goオンラインコンパイラ