为什么我在接收通道值时看不到输出?

huangapple go评论88阅读模式
英文:

why I can not see output when received value by channel

问题

在下一个示例中,我不明白为什么在接收到时没有打印出 end 值。

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 来解决这个问题。

英文:

in the next example, I don't understand why end value not printed when received

package main

import &quot;fmt&quot;

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

	go func() {
		fmt.Println(&quot;Start&quot;)
		fmt.Println(&lt;-start)
	}()

	go func() {
		fmt.Println(&quot;End&quot;)
		fmt.Println(&lt;-end)
	}()

	start &lt;- 1
	end &lt;- 2
}

I know sync.WaitGroup can solve this problem.

答案1

得分: 1

因为程序在到达func main的结尾时退出,而不管是否有其他goroutine正在运行。一旦第二个函数从end通道接收到数据,main函数对该通道的发送操作将被解除阻塞,程序将在将接收到的值传递给Println之前结束。

英文:

Because the program exits when it reaches the end of func main, regardless of whether any other goroutines are running. As soon as the second function receives from the end channel, main's send on that channel is unblocked and the program finishes, before the received value gets a chance to be passed to Println.

答案2

得分: 0

结束值没有被打印出来,因为一旦主goroutine(实际上是main函数的一个goroutine)完成(换句话说,解除阻塞),其他非主goroutine就没有机会完成。当函数main()返回时,程序退出。此外,goroutine是独立的执行单元,当一系列goroutine一个接一个地启动时,你不能依赖于goroutine实际启动的顺序。你的代码逻辑必须独立于goroutine调用的顺序。

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

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

英文:

The end value is not printed because as soon as the main goroutine (the main function is actually a goroutine) is finished (in other terms get unblocked) the other non-main goroutines does not have the chance to get completed.

When the function main() returns, the program exits. Moreover goroutines are independent units of execution and when a number of them starts one after the other you cannot depend on when a goroutine will actually be started. The logic of your code must be independent of the order in which goroutines are invoked.

One way to solve your problem (and the easiest one in your case) is to put a time.Sleep at the end of your main() function.

time.Sleep(1e9)

This will guarantee that the main goroutine will not unblock and the other goroutines will have a change to get executed.

package main

import (
	&quot;fmt&quot;
	&quot;time&quot;
)

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

    go func() {
        fmt.Println(&quot;Start&quot;)
        fmt.Println(&lt;-start)
    }()

    go func() {
        fmt.Println(&quot;End&quot;)
        fmt.Println(&lt;-end)
    }()

    start &lt;- 1
    end &lt;- 2

    time.Sleep(1e9)
}

Another solution as you mentioned is to use waitgroup.

答案3

得分: 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("开始")
        fmt.Println(<-start)
    }()

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

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

Apart from sleep where you have to specify the time, you can use waitgroup to make you program wait until the goroutine completes execution.

package main

import &quot;fmt&quot;
import &quot;sync&quot;

var wg sync.WaitGroup

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

	wg.Add(2)
	go func() {
		defer wg.Done()
		fmt.Println(&quot;Start&quot;)
		fmt.Println(&lt;-start)
	}()

	go func() {
		defer wg.Done()
		fmt.Println(&quot;End&quot;)
		fmt.Println(&lt;-end)
	}()

	start &lt;- 1
	end &lt;- 2
	wg.Wait()
}

huangapple
  • 本文由 发表于 2016年4月20日 11:15:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/36733182.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定