Go 所有通道都处于死锁状态

Go 所有通道都处于死锁状态,go,channel,Go,Channel,我正在尝试使用一个for循环,它不断地将字符串发送到不同goroutine读取的不同通道。然而,它给了我一个错误“所有goroutines都处于休眠状态-死锁!”为什么会发生这种情况?我寻找了一些答案,但我找不到这种情况的答案 func main() { var chans []chan string for i := 0; i < 3; i++ { chans = append(chans, make(chan string)) } f

我正在尝试使用一个for循环,它不断地将字符串发送到不同goroutine读取的不同通道。然而,它给了我一个错误“所有goroutines都处于休眠状态-死锁!”为什么会发生这种情况?我寻找了一些答案,但我找不到这种情况的答案

func main() {
    var chans []chan string

    for i := 0; i < 3; i++ {
        chans = append(chans, make(chan string))
    }

    for i := 0; i < 3; i++ {
        go sendString(chans[i])
    }

    for str := range chans[0] {
        fmt.Print(str)
    }
}

func sendString(ch chan string) {
    ch <- "a"
    ch <- "b"
    ch <- "c"
    ch <- "d"
}

我使用WaitGroup编写了这个版本,但它似乎不正确,并给出了相同的错误“所有goroutines都处于休眠状态-死锁!”我在下面的代码中哪里做错了

func main() {
var myWaitGroup sync.WaitGroup
ch := make(chan string)
myWaitGroup.Add(1)
go sendString(ch, &myWaitGroup)


myWaitGroup.Wait()
close(ch)

time.Sleep(1 * time.Second)
}
func sendString(ch chan string, pg *sync.WaitGroup) {
ch <- "a"
ch <- "b"
ch <- "c"
ch <- "d"
defer pg.Done()

}
func main(){
var myWaitGroup sync.WaitGroup
ch:=制造(成串)
myWaitGroup.Add(1)
go sendString(ch和myWaitGroup)
myWaitGroup.Wait()
关闭(ch)
时间。睡眠(1*时间。秒)
}
func sendString(ch chan string,pg*sync.WaitGroup){

ch第二个for循环将阻塞,直到通道关闭,因此您需要在发送函数中关闭它。此外,您只从第一个通道读取,因此一些数据丢失。执行此操作:

func main() {
    var chans []chan string

    for i := 0; i < 3; i++ {
        chans = append(chans, make(chan string))
    }

    for i := 0; i < 3; i++ {
        go sendString(chans[i])
    }

    for i := 0; i < 3; i++ {
        for str := range chans[i] {
            fmt.Print(str)
        }
    }

}
func sendString(ch chan string) {
    ch <- "a"
    ch <- "b"
    ch <- "c"
    ch <- "d"
    close(ch)
}

如果您希望根据您的评论使用单个频道执行此操作,则可以添加一个等待组,以便在所有go例程完成后关闭频道:

func main() {
    c := make(chan string)
    var wg sync.WaitGroup

    for i := 0; i < 3; i++ {
        wg.Add(1)
        go func() {
            sendString(c)
            wg.Done()
        }()
    }

    go func() {
        wg.Wait()
        close(c)
    }()

    for str := range c {
        fmt.Print(str)
    }

}
func sendString(ch chan string) {
    ch <- "a"
    ch <- "b"
    ch <- "c"
    ch <- "d"
}
func main(){
c:=制造(成串)
var wg sync.WaitGroup
对于i:=0;i<3;i++{
工作组.添加(1)
go func(){
发送字符串(c)
wg.Done()
}()
}
go func(){
wg.Wait()
关闭(c)
}()
对于str:=范围c{
格式打印(str)
}
}
func sendString(ch chan string){

对于这个问题,我猜@Tripkinetics可能是重复的,他关闭了通道,并使用另一个通道输出结果,但我想说的是,有没有一种方法可以只使用一个通道打印通道中的元素,而不使用另一个Goroutine中的接收函数如果你想将所有字符串放在一个通道中,你可以使用sync.WaitGroup等待所有go例程完成,然后关闭主go routineThanks中的通道!我也使用WaitGroup制作了一个版本,但它给了我相同的错误,代码如上,为什么会产生错误?使用WaitGroup时我必须使用匿名函数吗?给通道一个大小,否则它会阻止u直到有人从中读到:。这里的更多信息显然这需要知道有多少东西会提前发送到频道,而在另一个例程中关闭频道并不太感谢您,我还有一个问题,在您给出的第一个示例中,它没有明确说明频道的大小,但为什么频道可以包含四个字符串没有任何接收功能?第二个for循环中的范围接收。这在初始代码中不起作用,因为死锁发生在第二个for循环结束时,通道从未关闭。在初始等待组代码中,它在发送中锁定。
func main() {
    c := make(chan string)
    var wg sync.WaitGroup

    for i := 0; i < 3; i++ {
        wg.Add(1)
        go func() {
            sendString(c)
            wg.Done()
        }()
    }

    go func() {
        wg.Wait()
        close(c)
    }()

    for str := range c {
        fmt.Print(str)
    }

}
func sendString(ch chan string) {
    ch <- "a"
    ch <- "b"
    ch <- "c"
    ch <- "d"
}