我正在创建一个使用字符串值的简单 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的长度。

然后,您使用一个循环其resultsfor 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
}

09-25 19:30
查看更多