考虑以下go playground
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个正在运行的goroutine,它们会监听通道以发出信号打印或关闭。
但是上面的代码遇到了死锁。
我不确定为什么
有人可以指出我的错误吗?
由于
答案 0 :(得分:4)
有一些问题:
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!
你的goroutines已经完成了没有goroutines倾听到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
答案 1 :(得分:1)
当goroutines运行时,变量i
已经递增。将其作为函数参数传递。
实际上,永远不要依赖goroutines中函数闭包的变量。这太不可靠了。