LoginSignup
22
17

More than 5 years have passed since last update.

golangでデストラクタ的なことをする

Last updated at Posted at 2015-01-07

golangはstructにデストラクタ的なものを定義することは出来ないが、インスタンスがGCに拾われる時に任意の処理をさせることはできる。

具体的方法

runtimeパッケージのSetFinalizer()でfinalizer関数を設定できる。いわゆるデストラクタのようにstructの宣言に付けられるわけではなくて、インスタンスごとに設定しなければならない。
# なのでデストラクタではない

createInstance()でfinalizer関数を設定している。runtime.SetFinalizerには対象のインスタンスの参照とfinalizerとして設定する関数を渡す。

partial
func finalizer(m *string) {
        fmt.Println("finalize for ->", *m)
        return
}

func createInstance() {
        x := "hello"
        runtime.SetFinalizer(&x, finalizer)
        return
}

func main() {
        createInstance()
        runtime.GC()
        time.Sleep(1 * time.Second)
        return
}
output
finalize for -> hello

finalizer関数は新しく立ち上げられたgoroutineで実行される。(このgoroutineが実行される時間をsleepで稼いでる)
finalizer()で出力させている文字列が出ていて、GCで回収されたタイミングで実行されていることが判る。

注意点

  • SetFinalizerを使用したインスタンスは、Finalizerが動作したタイミングではGCに回収されない。次回のGCで回収される。
  • finalizer関数は必ず実行されるわけではない。つまり、GCに回収されないケース(プロセスが終了する・GCが止まっている)は漏れる。
    • deferであれば確実に実行される

用途

あんまり綺麗じゃないし確実でもないので、積極的には使わないほうがいいような気がする。
個人的には、型じゃなくてインスタンスによって重要な動作が変わるのが、ヒジョーに気持ち悪い。
# 美観の問題かもだけど、deferで間に合うように書いたほうが読みやすい

とはいえcgoでc言語の関数をラップするとかの時とか、まぁどうしようもない事が時々ある。そんなときにだけ使いたい。

22
17
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
22
17