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):
В рабочем, ch = 1
Финализатор
Я ожидаю, что эта программа заблокируется. runtime.GC()
не будет собирать s
, так как worker()
содержит ссылку на s.chs
.
Однако он заканчивается с go 1.8.3. В финализаторе s
успешно вызывается даже close(s.chs)
.
Интересно, имеет ли это какое-то особое отношение к range
и GC.
Спасибо большое.
s
больше не будет использоваться. Сделайтеs
глобальным, и он заблокируется. - person JimB   schedule 07.09.2017Close()
для типов, которые обертывают FD и сокеты. См. также. - person kostix   schedule 08.09.2017