我正在创建一个采用字符串值的简单频道。但显然我是在字符串中推送每个字母而不是每个循环中的整个字符串。
我可能错过了一些非常基本的东西。我做错了什么?
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))
}
}
答案 0 :(得分:4)
您的代码正确地在频道上发送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
将是从频道收到的单值(在其上发送的第一个值)。然后打印此string
的长度。
然后使用results
循环遍历此字符串(for range
),并在rune
s上循环显示这些字符串。
你想要的是循环通道的值:
// print the items in channel
for s := range c {
fmt.Println(s)
}
运行时会导致运行时出现紧急情况:
fatal error: all goroutines are asleep - deadlock!
因为您从未关闭频道,并且频道上的for range
会一直运行,直到频道关闭。所以你必须在某个时候关闭频道。
例如,让我们等待1秒,然后关闭它:
go func() {
time.Sleep(time.Second)
close(c)
}()
这样您的应用程序将在1秒后运行并退出。在 Go Playground 上试试。
另一个更好的解决方案是使用sync.WaitGroup
:这等待所有goroutine完成其工作(在通道上发送值),然后关闭通道(因此没有不必要的等待/延迟)
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
}
答案 1 :(得分:0)
你要取回字母而不是字符串的原因是你将通道结果分配给变量并迭代分配给这个变量的通道的结果,在你的情况下是一个字符串,在Go中你可以迭代一个带有for range
循环的字符串以获取符文。
您只需打印频道,而无需迭代频道结果。
package main
import (
"fmt"
)
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))
fmt.Println(results) // will print helloooo
}