为什么context.Context信号会影响新的goroutine?

时间:2019-09-02 06:59:03

标签: go

我正在使用context.Context来控制多个goroutine。 goroutine监听context.Done(),然后立即打印日期字符串。然后,该进程监听syscall.SIGHUP,该操作会取消上下文,然后使用之前创建的上下文创建新的goroutine。

我认为,当syscall.SIGHUP发出时,该过程将打印一个日期字符串,但是打印了两个。

此过程正在ubuntu18.04上运行。

package main

import (
    "context"
    "fmt"
    "os"
    "os/signal"
    "syscall"
    "time"
)

func main() {
    ctx, cancel := context.WithCancel(context.Background())
    go printDate(ctx)

    sg := make(chan os.Signal)
    signal.Notify(sg, syscall.SIGHUP)

    for {
        select {
        case <-sg:
            cancel()
            go printDate(ctx)
        }
    }
}

func printDate(ctx context.Context) {
    select {
    case <-ctx.Done():
        fmt.Println(time.Now().Format("2006-01-02 15:04:05"))
    }
}

我希望输出为

2019-01-02 01:02:03

但实际输出是:

2019-01-02 01:02:03
2019-01-02 01:02:03

1 个答案:

答案 0 :(得分:2)

cancel()完成后,ctx会永远保留下去。因此,当您第二次调用go printDate(ctx)时,您将使用一个完成的Context调用printDate,并且案例可以因为ctx而运行。Done()返回一个封闭的通道,您可以从一个封闭的通道接收该信号。