首页 > 解决方案 > 如何在不出现死锁错误的情况下获得所有结果

问题描述

应该从切片中获取所有值,最终不会出现死锁。当我不使用 waitGroups 时,我没有收到死锁错误。 <-time.After(time.Second) 是我用来代替 waitGroup 的,这有帮助

package main

import (
    "fmt"
    "sync"
)

var wg sync.WaitGroup

func main() {
    c := make(chan int)

    a := []int{1, 3, 10, 8, 15, 23}

    wg.Add(len(a))

    go func(i []int) {
        for _, v := range i {
            c <- v
        }
    }(a)

    go Print(c)
    wg.Wait()
}

func Print(c chan int) {
    for v := range c {
        fmt.Println(v)
    }
    wg.Done()
    close(c)
}

标签: gochannels

解决方案


您对同步机制感到困惑。关键是要同步异步工作人员。不是他们将处理的元素数量。

您不会在写入结束后关闭通道,而是在读取应该结束后关闭。这是错误的。

您正在使生产者和消费者都异步。这有点奇怪。由于您已经在 main 中有一个线程,因此您可以利用它来不启动虚假例程。

修复后代码的一些变体

package main

import (
    "fmt"
    "sync"
)

var wg sync.WaitGroup

func main() {
    c := make(chan int)

    a := []int{1, 3, 10, 8, 15, 23}

    wg.Add(1) // one async worker
    go Print(c) // ensure the worker is started upfront

    for _, v := range a {
        c <- v // write the data
    }
    close(c) //then close

    wg.Wait()
    fmt.Println("done")
}

func Print(c chan int) {
    for v := range c { // the loop will break because the channel is closed.
        fmt.Println(v)
    }
    wg.Done()
}

您也可以在没有任何等待组的情况下构建它。

package main

import (
    "fmt"
)

func main() {
    c := make(chan int)

    a := []int{1, 3, 10, 8, 15, 23}

    go func() {
        for _, v := range a {
            c <- v // write the data
        }
        close(c) //then close
    }()

    for v := range c { // the loop will break because the channel is closed.
        fmt.Println(v)
    }
    fmt.Println("done")
}

推荐阅读