我正在创建一个使用字符串值的简单 channel 。但是很显然,我在推字符串中的每个字母,而不是每个循环中的整个字符串。
我可能缺少一些非常基本的东西。我究竟做错了什么 ?
https://play.golang.org/p/-6E-f7ALbD
代码:
func doStuff(s string, ch chan string) {
ch <- s
}
func main() {
c := make(chan string)
loops := [5]int{1, 2, 3, 4, 5}
for i := 0; i < len(loops); i++ {
go doStuff("helloooo", c)
}
results := <-c
fmt.Println("channel size = ", len(results))
// print the items in channel
for _, r := range results {
fmt.Println(string(r))
}
}
最佳答案
您的代码会在 channel 上正确发送string
:
func doStuff(s string, ch chan string){
ch <- s
}
问题出在接收方:
results := <- c
fmt.Println("channel size = ", len(results))
// print the items in channel
for _,r := range results {
fmt.Println(string(r))
}
results
将是从 channel 接收的单个值(在其上发送的第一个值)。然后打印此string
的长度。然后,您使用一个循环其
results
的for range
遍历此字符串(rune
),并打印它们。您想要的是循环 channel 的值:
// print the items in channel
for s := range c {
fmt.Println(s)
}
运行时会导致运行时出现紧急情况:
fatal error: all goroutines are asleep - deadlock!
因为您从不关闭 channel ,所以 channel 上的
for range
会一直运行到关闭 channel 为止。因此,您必须在某个时候关闭 channel 。例如,让我们等待1秒钟,然后将其关闭:
go func() {
time.Sleep(time.Second)
close(c)
}()
这样,您的应用将在1秒钟后运行并退出。在Go Playground上尝试一下。
另一个更好的解决方案是使用
sync.WaitGroup
:WAITING所有goroutine完成工作(在 channel 上发送一个值),然后关闭 channel (因此没有不必要的等待/延迟)。var wg = sync.WaitGroup{}
func doStuff(s string, ch chan string) {
ch <- s
wg.Done()
}
// And in main():
for i := 0; i < len(loops); i++ {
wg.Add(1)
go doStuff("helloooo", c)
}
go func() {
wg.Wait()
close(c)
}()
在Go Playground上尝试这个。
注意:
要重复5次,您不需要那个丑陋的
loops
数组。只需做:for i := 0; i < 5; i++ {
// Do something
}