Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby-on-rails-4/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用goroutine和闭包给出错误通过通道读取并发函数_Go_Synchronization_Closures_Channel_Goroutine - Fatal编程技术网

使用goroutine和闭包给出错误通过通道读取并发函数

使用goroutine和闭包给出错误通过通道读取并发函数,go,synchronization,closures,channel,goroutine,Go,Synchronization,Closures,Channel,Goroutine,我有一个函数(不是闭包)正在写入通道。我从一个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") brea

我有一个函数(不是闭包)正在写入通道。我从一个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()
}
印后

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


为什么尽管我将waitgroup增量增加了1,却给出了一个负的waitgroup计数器错误?使用另一个并发函数或闭包读取goroutine的最佳方式是什么?

中断
不会中断外部
for
循环。 要引用外部循环,可以使用如下标签:

Loop:
    for {
        select {
            case ...:
                break Loop
        }
    }
wgread.Add(1)
go func() {
    defer wgread.Done()
    for chanoutput := range somechan {
        fmt.Println(string(*chanoutput))
    }
    fmt.Println("DONE")
}()
wgread.Wait()
也有助于编码风格,
您应该练习使用格式化代码。例如,它将替换;{…}
使用{…}的清洁剂
时,{…}

中断
不会中断外部
for
循环。 要引用外部循环,可以使用如下标签:

Loop:
    for {
        select {
            case ...:
                break Loop
        }
    }
wgread.Add(1)
go func() {
    defer wgread.Done()
    for chanoutput := range somechan {
        fmt.Println(string(*chanoutput))
    }
    fmt.Println("DONE")
}()
wgread.Wait()
也有助于编码风格,
您应该练习使用格式化代码。例如,它将替换;{…}
对于{…}

使用cleaner
for{…}
时,break语句从最里面的for或switch语句中断开。在
somechan
上接收的函数在循环中旋转,在通道关闭时减少等待组。编写如下代码:

Loop:
    for {
        select {
            case ...:
                break Loop
        }
    }
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))
}

break语句从最里面的for或switch语句中分离出来。在
somechan
上接收的函数在循环中旋转,在通道关闭时减少等待组。编写如下代码:

Loop:
    for {
        select {
            case ...:
                break Loop
        }
    }
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))
}

这里没有足够的代码来说明问题。这里没有足够的代码来说明问题。谢谢@Baloo,但是使用break-Loop,主线程现在正在等待。谢谢@Baloo,但是使用break-Loop,主线程现在正在等待。