#go #goroutine
#Вперед #goroutine
Вопрос:
Я пытаюсь понять этот фрагмент кода, не уверен, почему 2-й запуск выполняется перед 1-м. Было бы здорово, если бы кто-нибудь действительно мог мне в этом помочь!
func sum(a []int, c chan int) {
fmt.Println("summing: ", a)
total := 0
for _, v := range a {
total = v
}
//fmt.Println("send to c",total)
c <- total // send total to c
}
func main() {
//a := []int{7, 2, 8,134,23,23,1,23,1234,143, -9, 4, 0, 1234}
c := make(chan int)
go sum([]int{1,2,3}, c)
go sum([]int{4,5,6}, c)
x := <-c
fmt.Println(x)
x = <-c
fmt.Println(x)
}
ВЫВОД:
summing: [4 5 6]
15
summing: [1 2 3]
6
Ответ №1:
У вас нет ничего явно синхронизирующего порядок двух программ. Если вы запустите это достаточно много раз, вы увидите вызовы для fmt.Println
печати в разных последовательностях. При выполнении процедур, поскольку они являются параллельными операциями, у вас нет никаких гарантий, когда они будут выполнены и / или завершены. Вам необходимо использовать различные пакеты стандартных библиотек или сами каналы для синхронизации выполнения одновременно запущенных программ.
Например (используя блокирующий характер каналов, вы могли бы сделать что-то вроде):
func main() {
c := make(chan int)
go sum([]int{1, 2, 3}, c)
//use the channel to block until it receives a send
x := <-c
fmt.Println(x)
//then execute the next routine
go sum([]int{4, 5, 6}, c)
x = <-c
fmt.Println(x)
}
Другой пример (значительно менее практичный, но здесь, чтобы посмотреть на другие общие функции синхронизации go), вы могли бы ввести группу ожидания и диапазон по каналу:
func sum(a []int, c chan int, wg *sync.WaitGroup) {
defer wg.Done()
fmt.Println("summing: ", a)
total := 0
for _, v := range a {
total = v
}
//fmt.Println("send to c",total)
c <- total // send total to c
}
func main() {
c := make(chan int)
wg := new(sync.WaitGroup)
//concurrently call the concurrent calls to sum, allowing execution to continue to the range of the channel
go func() {
//increment the wait group, and pass it to the sum func to decrement it when it is complete
wg.Add(1)
go sum([]int{1, 2, 3}, c, wg)
//wait for the above call to sum to complete
wg.Wait()
//and repeat...
wg.Add(1)
go sum([]int{4, 5, 6}, c, wg)
wg.Wait()
//all calls are complete, close the channel to allow the program to exit cleanly
close(c)
}()
//range of the channel
for theSum := range c {
x := theSum
fmt.Println(x)
}
}