Рутина и закрытие канала странное поведение - PullRequest
0 голосов
/ 05 мая 2019

Согласно Документация Голанга ,

Оператор 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
        }
    }
}

Что может быть основной причиной? У меня там просто БОЛЬШАЯ путаница.

...