尝试理解带有WaitGroup的go func函数。

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

Trying to understand go func with WaitGroup

问题

我有以下代码 https://play.golang.org/p/9jPlypO4d-

package main
import (
    "fmt"
    "sync"
    "time"
)

func main() {
    var wg sync.WaitGroup
    wg.Add(1)
    c := make(chan int)
    go func() {
        defer wg.Done()
        for {
            if <-c == -1 {
                fmt.Print(":")
                return
            }

            fmt.Print(".")
            time.Sleep(time.Second)
        }
    }()

    c <- 0
    time.Sleep(time.Second * 5)
    c <- -1
    wg.Wait()
}

我想知道为什么只打印了一个 .?难道不应该是4或5个吗?

英文:

I have the following code https://play.golang.org/p/9jPlypO4d-

package main
import (
    &quot;fmt&quot;
    &quot;sync&quot;
    &quot;time&quot;
)

func main() {
    var wg sync.WaitGroup
    wg.Add(1)
    c := make(chan int)
    go func() {
            defer wg.Done()
            for {
                    if &lt;-c == -1 {
                            fmt.Print(&quot;:&quot;)
                            return
                    }

                    fmt.Print(&quot;.&quot;)
                    time.Sleep(time.Second)
            }

    }()

    c &lt;- 0
    time.Sleep(time.Second * 5)
    c &lt;- -1
    wg.Wait()
}

I wonder why there is only one . printed? Shouldn't it be like 4 or 5?

答案1

得分: 3

if <-c == -1 会阻塞直到通道中有内容。所以,第一个值是0,它获取到了这个值,打印出一个.,休眠一秒钟(而在goroutine外部休眠5秒钟),然后阻塞直到获取到下一个值。然后它返回。

我所知道的唯一不阻塞读取通道的方法是使用带有默认情况的select语句。

go func() {
	defer wg.Done()
	for {
		select {
		case x, ok := <-c:
			if ok && x == -1 {
				fmt.Print(":")
				return
			}
		default:
			fmt.Print(".")
		}
		
		time.Sleep(time.Second)
	}

}()

链接:https://play.golang.org/p/nOG_hfih4D

英文:

if &lt;-c == -1 will block until there is something in the channel. So, the first value is 0, it gets it, prints out a ., sleeps one second (while outside the goroutine it is sleeping 5 seconds), then it blocks until it gets the next value. And then it returns.

The only way to read a channel without blocking (that I know of) is to use a select statement with a default case.

go func() {
	defer wg.Done()
	for {
		select {
		case x, ok := &lt;-c:
			if ok &amp;&amp; x == -1 {
				fmt.Print(&quot;:&quot;)
				return
			}
		default:
			fmt.Print(&quot;.&quot;)
		}
		
		time.Sleep(time.Second)
	}

}()

https://play.golang.org/p/nOG_hfih4D

huangapple
  • 本文由 发表于 2017年6月15日 07:30:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/44556231.html
匿名

发表评论

匿名网友

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

确定