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()
}
Output (go 1.8.3):
In worker, ch = 1
Finalizer
I expect this program to deadlock. runtime.GC()
will not collect s
, since worker()
holds a reference to s.chs
.
However it terminates with go 1.8.3. In the finalizer of s
, even close(s.chs)
is called successfully.
I wonder if it has something special do with range
and GC.
Thanks very much.