无法从通道获取值

  • 本文关键字:获取 通道 go
  • 更新时间 :
  • 英文 :


我在通道中插入了一些值。 之后,我试图将其从通道中取出,但它没有输出任何值并退出。有人知道为什么吗?

package main
import (
"fmt"
)
func main() {
c := make( chan string)
for _, s := range []string{"A", "B", "C"} {
fmt.Println( "input : ", s)
go func() {
c <- s 
}()
}
close( c)
// recive
for i := range c {
fmt.Println("output", i)
}
}

预期输出

input :  A
input :  B
input :  C
output : A
output : B
output : C

电流输出

input :  A
input :  B
input :  C

在通道中添加值之前,您的通道可能已关闭(close在 goroutines 的第一行之前调用(。那么频道中当然没有什么可读的。 与其使用 goroutines 在通道中添加值,不如切换到缓冲通道

,如下所示:
package main
import (
"fmt"
)
func main() {
inputs := []string{"A", "B", "C"}
c := make(chan string, len(inputs))
for _, s := range inputs {
fmt.Println( "input : ", s)
c <- s 
}
close(c)
// recive
for i := range c {
fmt.Println("output", i)
}
}

或者,您可以使用如下所示的候补组:

package main
import (
"fmt"
"sync"
)
func main() {
var wg sync.WaitGroup
inputs := []string{"A", "B", "C"}
c := make(chan string)
for _, s := range inputs {
fmt.Println( "input : ", s)
wg.Add(1)
go func(s string) {
c <- s
wg.Done()
}(s)
}
go func(){
wg.Wait()
close(c)
}()
// recive
for i := range c {
fmt.Println("output", i)
}
}

在你的代码中有几个事情需要注意。

第一个是在闭包中使用 for 循环s变量。

go func() {
c <- s 
}()

在这里,您最终可能会得到不一致的值,因为您不知道这些 goroutines 何时执行。据您所知,您最终可能会将"C"写入频道三次。如果你想把它与单独的goroutine一起使用,可以像这样使用它:

go func(str string) {
c <- str 
}(s)

至于未从通道检索的值,通道在从中检索任何内容之前被关闭。 你可以写这样的东西:

package main
import (
"fmt"
)
func main() {
c := make( chan string)
go func(){
for _, s := range []string{"A", "B", "C"} {
fmt.Println( "input : ", s)
c <- s 
}
close( c)
}()
// recive
for i := range c {
fmt.Println("output", i)
}
}

但即使这样也会给你这样的输出(甚至这可能会有所不同(:

input :  A
input :  B
output A
output B
input :  C
output C

为了获得你想要的输出,你可能需要使用缓冲通道和某种机制来防止读取,直到所有内容都写入通道。也许是这样的:

package main
import (
"fmt"
"sync"
)
func main() {
c := make( chan string,3)
var wg sync.WaitGroup
wg.Add(3)
for _, s := range []string{"A", "B", "C"} {
fmt.Println( "input : ", s)
c <- s 
}

go func(w *sync.WaitGroup){
// recive
for i := range c {
fmt.Println("output", i)
w.Done()
}
}(&wg)
wg.Wait()
close(c)
}

最新更新