通道结束父例程后返回

时间:2018-02-28 04:59:38

标签: go concurrency

我有一个运行go例程的主程序的代码摘录。为什么这不会发生:主要退出收到完成后和作业返回之前,这将使孩子处理僵尸。任何对golang文档的引用都会有所帮助。

func main() {
    var jobDone = make(chan bool)
    go job(jobDone)
    <-jobDone
}

func job(done chan bool) {
    for {
        select {
        case <-someOtherGlobalChannel:
            //Please ignore this case/channel
            fmt.Println("SOmeOtherChannel received")
        default:
            if check_somthing_expression {
                done <- true
                return
            }
        }
    }
}

3 个答案:

答案 0 :(得分:2)

通过这些更改,您的主要将在完成频道后退出

package main

import (
    "fmt"
)

func main() {
    var jobDone = make(chan bool)
    go job(jobDone)
    <-jobDone
}

func job(done chan bool) {
    for {
        select {
        case <-someOtherGlobalChannel:
            //Please ignore this case/channel
            fmt.Println("SOmeOtherChannel received")
        default:
            if check_somthing_expression {
                done <- true
                return
            }
        }
    }
}

答案 1 :(得分:1)

Zombie Process

  

“......这会让孩子处理僵尸”

go job()没有开始一个单独的过程,它启动另一个goroutine。您在此计划中拥有main goroutine和job goroutine。 Language spec

  

“go”语句在同一地址空间内作为独立的并发控制线程或goroutine开始执行函数调用。

因此,您不会创建Unix僵尸进程。

主要不在作业前退出

  

“为什么这不会发生:主要退出收到完成后和工作返回之前......?”

原因#1:接收操作阻止两个Goroutines

(1)因为done中的频道job没有发送声明。

<-done

是接收操作。见"Receive operator" in Go spec

  

对于频道类型的操作数ch,接收操作<-ch的值是从频道ch收到的值。

另见"Send statements" in Go spec

  

ch <- 3 // send value 3 to channel ch

您需要发送声明。 E.g:

done <- true

the Go TourEffective Go中提供了更多解释性文字和示例。

......还有第二个原因:

原因#2:发送和返回之间没有任何关系

(2)因为,即使你将接收操作更改为发送语句,在它发送到通道并返回之间的作业goroutine中也没有任何关系,因此它不可能在任何时间从一个通过到下一个。如果您希望这样,请使用time package

在作业中添加睡眠
done <- true
time.Sleep(time.Second * 30)
return

答案 2 :(得分:0)

你需要给你完成的频道添加一些bool消息,然后<-jobDone }可以得到一些消息来完成该块