Тупик при порождении горутина в цикле
Рассмотрим следующую игровую площадку
package main
import "fmt"
func main() {
var chan_array [2]chan int
chan1 := make(chan int)
chan2 := make(chan int)
chan_array[0] = chan1
chan_array[1] = chan2
for i := 0; i < 2; i++ {
go func() {
select {
case x := <- chan_array[i]:
if (x == 0) {
return
}
fmt.Println(x)
}
}()
}
chan1<- 1
chan2<- 2
chan1<- 0
chan2<- 0
}
Приведенный выше код пытается создать 2 запущенные программы, которые прослушивают канал, чтобы подать сигнал на печать или закрытие.
Но приведенный выше код работает в тупик.
Я не совсем уверен, почему
Может кто-нибудь указать на мою ошибку?
Спасибо
2 ответа
Есть некоторые проблемы:
Какова стоимость i
когда chan_array[i-1]
работает:
for i := 0; i < 2; i++ {
go func() {
select {
case x := <- chan_array[i-1]:
if x == 0 {
return
}
fmt.Println(x)
}
}()
}
попробуй это:
for i := 0; i < 2; i++ {
go func(i int) {
select {
case x := <-chan_array[i]:
if x == 0 {
return
}
fmt.Println(x)
}
}(i)
}
Давайте упростим ваш код (с некоторыми исправлениями):
package main
import "fmt"
func main() {
chan1 := make(chan int)
chan2 := make(chan int)
go routine(chan1)
go routine(chan2)
chan1 <- 1
chan2 <- 2
chan1 <- 0
chan2 <- 0
}
func routine(ch chan int) {
select {
case x := <-ch:
if x == 0 {
return
}
fmt.Println(x)
}
}
С этими:
chan1 <- 1
chan2 <- 2
фатальная ошибка:
all goroutines are asleep - deadlock!
твои горутины закончились и никаких гурутин не слушали chan1
а также chan1
Вот:
chan1 <- 0
chan2 <- 0
Ваш исправленный рабочий пример кода:
package main
import "fmt"
func main() {
chan1 := make(chan int)
chan2 := make(chan int)
go routine(chan1)
go routine(chan2)
chan1 <- 1
chan2 <- 2
chan1 <- 0
chan2 <- 0
}
func routine(ch chan int) {
for {
select {
case x := <-ch:
if x == 0 {
return
}
fmt.Println(x)
}
}
}
выход:
1
2
К тому времени, как goroutines запускают переменную i
уже увеличился. Вместо этого передайте его как параметр функции.
На самом деле, никогда не полагайтесь на переменные из замыкания функций в функциях. Это слишком ненадежно.