为什么我不能通过频道收到值时看到输出

时间:2016-04-20 03:15:47

标签: go concurrency

在下一个例子中,我不明白为什么收到

时不打印结束值
package main

import "fmt"

func main() {
    start := make(chan int)
    end := make(chan int)

    go func() {
        fmt.Println("Start")
        fmt.Println(<-start)
    }()

    go func() {
        fmt.Println("End")
        fmt.Println(<-end)
    }()

    start <- 1
    end <- 2
}

我知道sync.WaitGroup可以解决这个问题。

3 个答案:

答案 0 :(得分:1)

因为程序在到达func main结束时退出,无论是否有其他goroutine正在运行。一旦第二个功能从end频道收到,该频道上的主要发送被取消阻止并且程序结束,然后收到的值有机会传递给Println。 / p>

答案 1 :(得分:0)

不会打印结束值,因为只要main goroutine(main函数实际上是goroutine)完成(换句话说取消阻止),其他非主要goroutines就不会打印有机会完成。

当函数main()返回时,程序退出。此外goroutines是独立的执行单元,当它们中的一个一个接一个地启动时,你不能依赖于goroutine实际上何时会开始。代码的逻辑必须独立于调用goroutine的顺序。

解决问题的一种方法(在您的情况下最简单的方法)是在time.Sleep函数的末尾添加main()

time.Sleep(1e9)

这样可以保证主goroutine不会解锁,而其他goroutine会有更改来执行。

package main

import (
    "fmt"
    "time"
)

func main() {
    start := make(chan int)
    end := make(chan int)

    go func() {
        fmt.Println("Start")
        fmt.Println(<-start)
    }()

    go func() {
        fmt.Println("End")
        fmt.Println(<-end)
    }()

    start <- 1
    end <- 2

    time.Sleep(1e9)
}

您提到的另一种解决方案是使用waitgroup

答案 2 :(得分:0)

除了必须指定时间的睡眠之外,您可以使用waitgroup让程序等待,直到goroutine完成执行。

package main

import "fmt"
import "sync"

var wg sync.WaitGroup

func main() {
    start := make(chan int)
    end := make(chan int)

    wg.Add(2)
    go func() {
        defer wg.Done()
        fmt.Println("Start")
        fmt.Println(<-start)
    }()

    go func() {
        defer wg.Done()
        fmt.Println("End")
        fmt.Println(<-end)
    }()

    start <- 1
    end <- 2
    wg.Wait()
}