Согласно Документация Голанга ,
Оператор defer
помещает вызов функции в список. Список сохраненных вызовов выполняется после возврата окружающей функции. Defer обычно используется для упрощения функций, которые выполняют различные действия по очистке.
Другими словами, go defer
временно приостанавливает выполнение команды, пока не вернется окружающая функция.
Я написал простую программу go, которая содержит несколько goroutines, которые должны завершить 8 reader
goroutines после завершения goroutine looper
.
func main(){
// declaring handler
handler := make(chan int)
var wg sync.WaitGroup
// execute reader as 8 separate processes
for i := 0; i < 8; i++ {
go reader(handler, &wg)
}
// timer which fires an event once in a second
ticker := time.NewTicker(1 * time.Second)
// the channel which carries out termination signal
terminator := make(chan interface{})
go looper(ticker.C, handler, terminator)
// wait for 5 Seconds
time.Sleep(time.Second * 5)
// terminate looper
close(terminator)
//wait for reader functions to do their work
wg.Wait()
}
// receive val from looper and process it
func reader(handler <-chan int, wg *sync.WaitGroup) {
wg.Add(1)
defer wg.Done()
for val := range handler {
fmt.Printf("Received %d\n", val)
time.Sleep(2 * time.Second) //just to simulate a lengthy process
}
}
в программе, если я закрываю канал обработчика, используя defer
, он работает нормально.
func looper(ticker <-chan time.Time, handler chan<- int, terminator <-chan interface{}) {
arr := []int{1, 2, 3, 4, 5}
defer close(handler)
for {
select {
case <-ticker:
for _, val := range arr {
// passed the index to communication channel
handler <- val
}
case <-terminator:
return
}
}
}
Но если я закрою канал обработчика непосредственно перед оператором возврата следующим образом, программа существует, ничего не печатая
func looper(ticker <-chan time.Time, handler chan<- int, terminator <-chan interface{}) {
arr := []int{1, 2, 3, 4, 5}
for {
select {
case <-ticker:
for _, val := range arr {
// passed the val to reader
handler <- val
}
case <-terminator:
close(handler)
return
}
}
}
Что может быть основной причиной? У меня там просто БОЛЬШАЯ путаница.