我在通道中插入了一些值。之后,我尝试将其从通道中删除,但没有得到任何值并退出。有人知道为什么吗?
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
答案 0 :(得分:3)
在您在通道中添加值之前,您的通道可能已关闭(close
在goroutine的第一行之前被调用)。然后,当然在该频道中没有任何内容可读取。
不用使用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)
}
}
或者您可以像这样使用WaitGroup:
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)
}
}
答案 1 :(得分:1)
代码中有几件事需要注意。
第一个是闭包中for循环中s
变量的用法。
go func() {
c <- s
}()
在这里,您可能会得到不一致的值,因为您不知道何时执行这些goroutine。据您所知,您最终可能会在该通道上写3次“ 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)
}