在线文档 > Golang练习 > 信号
有时我们希望我们的 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)
// 我们可以在这里的 main 函数中从 `sigs` 接收信号,
// 但让我们看看如何在单独的 goroutine 中执行此操作,以演示更逼真的场景,即优雅关机。
done := make(chan bool, 1)
go func() {
// 此 goroutine 执行阻塞接收信号。
// 当它收到信号时,它会将其打印出来,并通知程序可以完成了。
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