go - 使用 goroutine 和闭包从并发函数读取并发错误

标签 go synchronization closures channel goroutine

我有一个正在写入 channel 的函数(不是闭包)。我正在从 goroutine 中调用该函数作为

var wg sync.WaitGroup
wg.Add(1)
go DoStuff(somechan, &wg)

在 DoStuff 中,我有类似的东西

for ; ; {

    if err == io.EOF { 
        fmt.Println(err)
        close(somechan)
        fmt.Println("Closed channel")
        break
    } else if err != nil {
        panic(err)
    }
    somechan <- Somefunc()
}

现在我正在尝试使用另一个 goroutine 从该 channel 读取数据。

wgread.Add(1)
go func() {
    for ; ; {
        select {
        case chanoutput, ok := <-somechan:
            if ok == true {
                fmt.Println(string(*chanoutput))
            } else {
                fmt.Println("DONE")
                fmt.Println(ok)
                wgread.Done()
                break
            }
        }

    }
}()
wgread.Wait()

但是,在运行时,我得到了

panic: sync: negative WaitGroup counter

打印后

DONE
false
DONE
false

如果我给 wgread.Add(2),它会打印上面的 DONE 和 false 3 次。

虽然我将 WaitGroup 增量递增 1,但为什么给出负 WaitGroup 计数器错误?使用另一个并发函数或闭包从 goroutine 读取数据的最佳方式是什么?

最佳答案

break 语句跳出最内层的 case,for 或 switch 语句。在 somechan 上接收的函数在一个循环中旋转,当 channel 关闭时递减 WaitGroup 。编写代码如下:

wgread.Add(1)
go func() {
    defer wgread.Done()
    for chanoutput := range somechan {
        fmt.Println(string(*chanoutput))
    }
    fmt.Println("DONE")
}()
wgread.Wait()

如果接收代码如题中所写,则接收goroutine可以消除。将 wgread.Add(1) 中的代码替换为 wgread.Wait()

for chanoutput := range somechan {
    fmt.Println(string(*chanoutput))
}

关于go - 使用 goroutine 和闭包从并发函数读取并发错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38976377/

相关文章:

linux - 为什么在 golang、linux 中使用 archive/zip 时文件名会变得困惑?

javascript - 以它们之间的延迟运行操作

javascript - 是否可以在Javascript中的setTimeout()方法中使 "value"自增?

javascript - 闭包出了问题——为什么匿名函数最后返回

oracle - 如何连接到 Oracle 数据库?

sockets - golang tcp套接字在获取文件()后无法关闭

go - 词汇文件名顺序是什么意思?

c# - 如何在 C# 应用程序之间同时同步数据刷新

java - 同步集合/列表的映射

swift - 如何让 For 循环在迭代到下一个元素之前等待回调?