遍历通道时出现错误 "too many variables in range"

Error "too many variables in range" when iterating over a channel

我有点迷路了,我试图让一个 goroutine 添加到数组中,并让另一个 goroutine 从中读取,我怀疑这与我下面的内容有些接近,但我需要尝试一下与 wait().

但是,我收到错误 prog.go:19:14: too many variables in range,第 19 行是 for _, v := range c { 我无法在线找到该问题的答案,我在这里做什么或不做什么?

package main

import (
    "fmt"
    //"time"
    "sync"
)

func hello(wg *sync.WaitGroup, s []int, c chan int) {
    for _, v := range s {
        c <- v
    }
    fmt.Println("Finished adding to channel")
    wg.Done()
}

func hello2(wg *sync.WaitGroup, c chan int) {
    fmt.Println("Channel",c)
    for _, v := range c {
        fmt.Println("Received",v)   
    }
    fmt.Println("Finished taking from channel")
    wg.Done()
}

func main() {
    s := []int{1, 2, 3, 4, 5}
    var c = make(chan int, 5)


    var wg sync.WaitGroup
    wg.Add(1)
    go hello(&wg, s, c)
    wg.Wait()
    wg.Add(1)
    go hello2(&wg, c)
    wg.Wait()
    //time.Sleep(1 * time.Second)
    fmt.Println("main function")
}

当您遍历通道时,迭代只会产生一个值,即在通道上发送的值。没有像切片或映射那样的索引或键值。

所以你必须使用:

for v := range c {
    fmt.Println("Received", v)   
}

这在Spec: For statements:

中有详细说明

If the range expression is a channel, at most one iteration variable is permitted, otherwise there may be up to two.

并且:

For channels, the iteration values produced are the successive values sent on the channel until the channel is closed. If the channel is nil, the range expression blocks forever.

还有:

Function calls on the left are evaluated once per iteration. For each iteration, iteration values are produced as follows if the respective iteration variables are present:

Range expression                          1st value          2nd value

array or slice  a  [n]E, *[n]E, or []E    index    i  int    a[i]       E
string          s  string type            index    i  int    see below  rune
map             m  map[K]V                key      k  K      m[k]       V
channel         c  chan E, <-chan E       element  e  E

我知道你没有intending/wishing为你的通道使用迭代器来进行范围循环,但是如果你确实希望有一个迭代器,它仍然可以通过在循环之外自己定义迭代器,并在每次读取通道中的值时递增它。

    var wg sync.WaitGroup
    var iterator = 0
    for v := range c1 {
        wg.Add(1)
        iterator += 1
        go func(v2, i2 int) {
            c2 <- timeConsumingWork(v2)
            fmt.Println("item ", i2, " done")
            wg.Done()
        }(v, iterator)
    }
    wg.Wait()
    close(c2)

}

在这里您可以看到 go func 正在接受通道值 (v2) 和迭代器值 (i2),同时每次从通道读取值时递增它。

此外,我看到您使用缓冲等待组来避免阻塞两个方法的顺序调用。理想的 Go 代码应该尽可能避免缓冲通道,而是以互锁的方式调用发送和接收函数,这样它们就不需要分开了。