Go 示例: 信号

有时我们希望我们的 Go 程序能够智能地处理 Unix 信号。例如,我们可能希望服务器在收到 SIGTERM 时优雅地关闭,或者命令行工具在收到 SIGINT 时停止处理输入。以下是使用通道在 Go 中处理信号的方法。

package main
import (
    "fmt"
    "os"
    "os/signal"
    "syscall"
)
func main() {

Go 信号通知通过在通道上发送 os.Signal 值来工作。我们将创建一个通道来接收这些通知。请注意,此通道应该是带缓冲的。

    sigs := make(chan os.Signal, 1)

signal.Notify 将给定通道注册为接收指定信号的通知。

    signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)

我们可以在主函数中从 sigs 中接收,但让我们看看如何在单独的 goroutine 中完成此操作,以演示更现实的优雅关闭场景。

    done := make(chan bool, 1)

此 goroutine 执行对信号的阻塞接收。当它收到一个信号时,它会打印出来,然后通知程序它可以完成。

    go func() {
        sig := <-sigs
        fmt.Println()
        fmt.Println(sig)
        done <- true
    }()

程序将在此处等待,直到它收到预期的信号(如上面的 goroutine 在 done 上发送值所指示的),然后退出。

    fmt.Println("awaiting signal")
    <-done
    fmt.Println("exiting")
}

当我们运行此程序时,它将阻塞等待信号。通过键入 ctrl-C(终端显示为 ^C),我们可以发送 SIGINT 信号,导致程序打印 interrupt 然后退出。

$ go run signals.go
awaiting signal
^C
interrupt
exiting

下一个示例:退出.