package main
import (
"sync"
"runtime"
)
type S struct {
chs chan int
}
var wg sync.WaitGroup
func worker(s *S) {
for i := range s.chs {
println("In worker, ch = ", i)
}
wg.Done()
}
func main() {
s := S{make(chan int)}
runtime.SetFinalizer(&s, func(ss *S) {
println("Finalizer")
close(ss.chs)
})
wg.Add(1)
go worker(&s)
for i := 0; i < 1; i++ {
s.chs <- 1
}
runtime.GC()
wg.Wait()
}
出力は(1.8.3を行く) 'の範囲' とGolangの 'チャンネル' に関連したガベージコレクション:バグまたは機能?
労働者で、CH = 1人の
ファイナ
私はこのプログラムがデッドロックすることを期待しています。 runtime.GC()
は、worker()
がs.chs
への参照を保持しているので、s
を収集しません。
ただし、1.8.3で終了します。 s
のファイナライザでは、close(s.chs)
でも正常に呼び出されます。
range
とGCで特別なことがあるのだろうかと思います。
ありがとうございました。
このようにrangeキーワードは特別なものではなく、コンパイラの最適化によって 's'が再び使用されないと判断できるということだけです。 's'をグローバルにして、デッドロックします。 – JimB
単に実験するのではなく、代わりに「デストラクタ」を実装しようとしている場合に備えて、私はあなたに警告しなければなりません。 Idiomatic Goのカスタム型は、FDやソケットをラップする型に対して 'Close()'のような明示的な "リソース解放/解放"メソッドを提供する必要があります。 [関連項目](https://stackoverflow.com/q/32768243/720999) – kostix