go编程实战的问题

ray1888 · 2017-12-06 15:13:31 · 1051 次点击 · 大约8小时之前 开始浏览    置顶
这是一个创建于 2017-12-06 15:13:31 的主题,其中的信息可能已经有所发展或是发生改变。

https://github.com/goinaction/code/tree/master/chapter2/sample,

这个是第二章的代码。个人还是不太能理解为什么在search/search.go上面可以通过一个go routine去等待waitGroup.wait(),而不用在run方法里面在原来的goroutine中进行waitGroup.wait0().因为之前写的代码以node和python为主,不太能理解为什么不用在主上面等待回调


有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1051 次点击  
加入收藏 微博
7 回复  |  直到 2017-12-07 03:29:55
ray1888
ray1888 · #1 · 7年之前

求熟悉go的大神解答一下

specita
specita · #2 · 7年之前

我觉得可以尝试waitGroup.wait()放到主方面里面,运行一下,看一下有没有什么差异来理解

eric160
eric160 · #3 · 7年之前

你说的是这一段吧:

go func() {
    // Wait for everything to be processed.
    waitGroup.Wait()

    // Close the channel to signal to the Display
    // function that we can exit the program.
    close(results)
}()

// Start displaying results as they are available and
// return after the final result is displayed.
Display(results)

这段go routine启动一个 monitor,等待上面所有的routine执行完成,然后关闭results. Display(results)也同时执行,Display方法是这样的:

func Display(results chan *Result) {
    // The channel blocks until a result is written to the channel.
    // Once the channel is closed the for loop terminates.
    for result := range results {
        log.Printf("%s:\n%s\n\n", result.Field, result.Content)
    }
}

一旦results关闭,for loop就结束。 这时Display方法就执行完毕,run方法也结束。

如果在run中直接去进行waitGroup.Wait(),就变成了这样:

    waitGroup.Wait()
    close(results)
    Display(results)

,那就会死锁,因为results是chan类型,上面的三个语句顺序执行,results只有进,没有出了。 而如果是这样: Display(results) waitGroup.Wait() close(results)

也会造成死锁,因为Display(results)一直在执行,等待results关闭,但是因为是顺序执行的,所以results无法关闭,所以会在最后死锁。 如果是这样:

    go func(){
            Display(results)
    }()
    waitGroup.Wait()
    close(results)

因为如果close了results,那run方法就直接退出,而如果Display没有执行完成,也会因为run退出而结束。不是好方法。

也许还有别的写法去进行执行,我个人认为例子中开个goroutine去监视的写法就很不错。

eric160
eric160 · #4 · 7年之前
specitaspecita #2 回复

我觉得可以尝试waitGroup.wait()放到主方面里面,运行一下,看一下有没有什么差异来理解

放main里不可以,因为results和waitGroup是run的局部变量,main里用不了。。。

eric160
eric160 · #5 · 7年之前
eric160eric160 #3 回复

你说的是这一段吧: go func() { // Wait for everything to be processed. waitGroup.Wait() // Close the channel to signal to the Display // function that we can exit the program. close(results) }() // Start displaying results as they are available and // return after the final result is displayed. Display(results) 这段go routine启动一个 monitor,等待上面所有的routine执行完成,然后关闭results. Display(results)也同时执行,Display方法是这样的: func Display(results chan *Result) { // The channel blocks until a result is written to the channel. // Once the channel is closed the for loop terminates. for result := range results { log.Printf("%s:\n%s\n\n", result.Field, result.Content) } } 一旦results关闭,for loop就结束。 这时Display方法就执行完毕,run方法也结束。 如果在run中直接去进行waitGroup.Wait(),就变成了这样: waitGroup.Wait() close(results) Display(results) ,那就会死锁,因为results是chan类型,上面的三个语句顺序执行,results只有进,没有出了。 而如果是这样: Display(results) waitGroup.Wait() close(results) 也会造成死锁,因为Display(results)一直在执行,等待results关闭,但是因为是顺序执行的,所以results无法关闭,所以会在最后死锁。 如果是这样: go func(){ Display(results) }() waitGroup.Wait() close(results) 因为如果close了results,那run方法就直接退出,而如果Display没有执行完成,也会因为run退出而结束。不是好方法。 也许还有别的写法去进行执行,我个人认为例子中开个goroutine去监视的写法就很不错。

jthmath
jthmath · #6 · 7年之前

在主routine里等待也行,不过那样的话,你的主routine在等待时就会停下来。如果你不希望主routine停下来,那就让另外的routine去等,否则无所谓

ray1888
ray1888 · #7 · 7年之前
eric160eric160 #5 回复

#3楼 @eric160 @ray1888

好的,学习了,其实可以,因为我一直以为主goroutine一定要等待,其实他这里也实现了阻塞了,只是用了channel results来进行阻塞(Display中进行range),而不是直接用waitGroup。感觉这个写法是比那个要好

添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传