遍历通道时出现错误 "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)
}
中有详细说明
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 代码应该尽可能避免缓冲通道,而是以互锁的方式调用发送和接收函数,这样它们就不需要分开了。
我有点迷路了,我试图让一个 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)
}
中有详细说明
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 代码应该尽可能避免缓冲通道,而是以互锁的方式调用发送和接收函数,这样它们就不需要分开了。