我在通道中插入了一些值。 之后,我试图将其从通道中取出,但它没有输出任何值并退出。有人知道为什么吗?
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)
}