gpt4 book ai didi

go - 所有 goroutines 都处于休眠状态

转载 作者:IT王子 更新时间:2023-10-29 02:03:39 24 4
gpt4 key购买 nike

我正在尝试使用 goroutines 和 channel

    package main

import (
"fmt"
"math/rand"
"time"
)

func boring(msg string) <-chan string {
c := make(chan string)
go func() {
for i := 0; ; i++ {
c <- fmt.Sprintf("%s %d", msg, i)
time.Sleep(time.Duration(rand.Intn(1e3)) * time.Millisecond)
}
}()
return c
}
func main() {
c := fanInNew(boring("joe"), boring("anh"))
for i := 0; i < 10; i++ {
fmt.Println(<-c)
}
fmt.Println("You both are boring, I am leaving")
}

func fanInNew(input1, input2 <-chan string) <-chan string {
c := make(chan string)
for {
select {
case s := <-input1:
c <- s
case s := <-input2:
c <- s
}
}
return c
}

如果我运行这个程序,它会给我错误,所有 goroutines 都睡着了,死锁。

但是如果我将 select 放在匿名 goroutine 中,它就可以正常工作。工作示例:

    package main

import (
"fmt"
"math/rand"
"time"
)

func boring(msg string) <-chan string {
c := make(chan string)
go func() {
for i := 0; ; i++ {
c <- fmt.Sprintf("%s %d", msg, i)
time.Sleep(time.Duration(rand.Intn(1e3)) * time.Millisecond)
}
}()
return c
}
func main() {
c := fanInNew(boring("joe"), boring("anh"))
for i := 0; i < 10; i++ {
fmt.Println(<-c)
}
fmt.Println("You both are boring, I am leaving")
}

func fanInNew(input1, input2 <-chan string) <-chan string {
c := make(chan string)
go func() {
for {
select {
case s := <-input1:
c <- s
case s := <-input2:
c <- s
}
}
}()
return c
}

你能帮我理解背后的原因吗。

最佳答案

for语句永远循环,所以 <-c chan 永远不会传递,chans 会被填满,但是 main线程卡住等待 c := fanInNew(a, b) .

fanInNew() 永远不会返回因为for 永远循环(并且select上阻塞 btw):

func fanInNew(input1, input2 <-chan string) <-chan string {
c := make(chan string)
for { // Loop forever and read from inputs 1 and 2
select {
case s := <-input1:
c <- s
case s := <-input2:
c <- s
}
}
return c
}

然后在主线程中这个函数永远不会返回c陈.

func main() {
// Never gets passed the next line
c := fanInNew(boring("joe"), boring("anh"))
}

所以你可以把for在 goroutines 中循环自己,就像你在第二个例子中所做的那样。 此外通常 goroutine 应该返回,因为您传入了一条消息(例如通过 close() ing),或者因为它们到达了 return 语句。

无论如何,第二个示例中的内容非常适合演示匿名闭包 的使用。 chan传递给 goroutine 的可以在别处返回并启用线程之间的安全消息传递:

c := make(chan string)
go func() {
for {
select {
case s := <-input1:
c <- s
case s := <-input2:
c <- s
}
}
}()
return c

有几种方法可以结束匿名 goroutine 中的 for 循环,包括在第二个上选择 chan ,一个关闭 channel ,当close()艾德你可以回来。此外,通常是 WaitGroups 可以做到这一点。

关于go - 所有 goroutines 都处于休眠状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41653695/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com