Почему канал goroutine делает это? - PullRequest
1 голос
/ 08 февраля 2020

Я новичок с golang. Я пытаюсь понять, как работают каналы, но это действительно сбивает с толку.

Я прокомментировал свои вопросы. Может кто-нибудь объяснить мне, почему этот код ведет себя так странно?

package main

import "fmt"

func main() {
    slice := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}
    c := make(chan int)
    go pokeVals(slice, c)

    fmt.Println(slice)
    fmt.Println("start")
    <-c // why 2 "poke"s here?
    fmt.Println("-")
    <-c // why 0 "poke"s?
    //<-c // But if uncommented - 2 more "pokes" here

    fmt.Println("end")
}

func pokeVals(values []int, c chan int) {
    for _, val := range values {
        fmt.Println("poke")
        c <- val
    }
    fmt.Println("overpoked")
}

Golang ссылка на игровую площадку: https://play.golang.org/p/u__cVyUbNJY

1 Ответ

3 голосов
/ 08 февраля 2020

Горутины запускаются одновременно. То, как они запланированы, не в ваших руках, единственная гарантия, которую вы получите относительно этого, - это если вы используете синхронизацию, такую ​​как каналы, группы ожидания или другие примитивы синхронизации.

С main() вы запускаете программу, которая отправляет значения на c в al oop. Но перед отправкой каждого значения сначала печатается "poke". Таким образом, вы можете увидеть один "poke" напечатанный, даже если вы не получили от c. Если вы получите значение от c, то l oop в этой процедуре может перейти к следующей итерации, которая снова печатает "poke", и может сделать это немедленно, даже до того, как программа main() попадет в печать. "-". Это то, что вы испытываете.

Процедура main() в исходной версии (3-я <-c закомментирована) прекращается (после печати "end"). Как только main() вернется, ваше приложение завершится, оно не будет ждать, пока другие программы завершат работу sh. Это то, что вы испытываете. Подробнее см. Нет вывода из goroutine .

Если вы раскомментируете 3-й <-c, тогда main() должен ждать еще одну отправку на c, что означает, что он определенно должен ждать для печати "poke" до этого. И как только goroutine pokeVals() сможет отправить другое значение на c, он может снова напечатать "poke" в циклах следующей итерации (если это запланировано раньше, чем возврат из main()), что вы испытываете .

Видите ли вы, что еще 2 напечатанных "poke" не определены c, 1 или 2 из них являются действительными результатами.

...