GC は自動的に実行されますが、手動で GC を実行したい場合は、runtime.GC() 関数を使用して明示的に GC を実行できます。明示的に GC を実行することは、メモリ リソースが不十分な場合に runtime.GC() を呼び出すなど、一部の特殊な場合にのみ役立ちます。これにより、すぐに大規模なメモリ領域が解放されますが、プログラムの短期的なパフォーマンス低下が発生します。
ファイナライザー (ターミネーター) は、オブジェクトに関連付けられた関数であり、 runtime.SetFinalizer によって設定されます。オブジェクトがファイナライザーを定義している場合、GC のときに、ファイナライザーが呼び出され、Signal の発行や書き込みなどの特定のタスクを完了します。ログなど
Go 言語では、SetFinalizer 関数は次のように定義されます。
func SetFinalizer(x, f interface{})
パラメータは次のように説明されます。
- パラメータ x は、new によって適用されたオブジェクトへのポインタ、または複合リテラル値をアドレス指定することによって取得されたポインタでなければなりません。
- 引数 f は、型 x の値を直接割り当てることができる単一の引数を受け入れる関数、または無視される戻り値を任意の数だけ持つことができる関数でなければなりません。
SetFinalizer 関数は x のファイナライザーを f に設定でき、ガベージ コレクターは x に直接的または間接的にアクセスできなくなったことを検出すると、x をクリーンアップして f(x) を呼び出します。
さらに、x のターミネータは、x に直接または間接的にアクセスできなくなった後はいつでも呼び出されて実行されます。プログラムが終了する前にターミネータが実行されるという保証はありません。そのため、一般的なターミネータは、プログラムを解放するためにのみ使用されます。長時間実行されるプログラム内の特定のプログラムに関連付けられたオブジェクトの非メモリ リソース。たとえば、プログラムが Close メソッドを呼び出さずに os.File オブジェクトを破棄すると、os.File オブジェクトはファイナライザーを使用して、対応するオペレーティング システムのファイル記述子を閉じることができます。
ファイナライザは依存関係の順序で実行されます。A が B を指し、両方にファイナライザがあり、A と B に他の関連付けがない場合、A のファイナライザが実行されて A が解放された後でのみ、B のファイナライザを実行できます。
また、*x のサイズが 0 バイトの場合にターミネータが実行されるという保証もありません。
さらに、 SetFinalizer(x, nil)
を使用して、x にバインドされたファイナライザーをクリーンアップすることもできます。
ヒント: ファイナライザーは、オブジェクトが GC の場合にのみ実行されます。それ以外の場合は、プログラムが正常終了またはエラーが発生しても実行されません。
【例】関数entry()内でローカル変数を定義し、ファイナライザを設定する関数entry()実行後、main関数内で手動でGCを起動し、ファイナライザの実行を確認します。
package main
import (
"log"
"runtime"
"time"
)
type Road int
func findRoad(r *Road) {
log.Println("ロード:",*r)
}
func entry() {
var rd Road = Road(999)
r := &rd
ランタイム.SetFinalizer(r, findRoad)
}
func main() {
エントリ()
for i := 0; i < 10; i++ {
time.sleep(time.Second)
runtime.GC()
}
}
操作の結果は次のようになります。
2023/05/17 15:32:16 road: 999