如何在 Golang 中处理信号?

在讨论信号以及如何处理它们之前,让我们先谈谈创建信号的常见场景。甲信号能够从终端传递,或者通过终止与的帮助程序CTRL + C,或者我们可以通过缺省调用Exit()该函数OS包为我们提供。

示例 1

让我们考虑一个例子,我们将在一个被延迟的函数声明之后调用该函数。os.Exit()

考虑下面显示的代码。

package main

import (
   "fmt"
   "os"
   "time"
)

func main() {
   defer func() {
      fmt.Println("Inside the deferred function()")
   }()

   fmt.Println("Inside the main function")
   time.Sleep(1 * time.Second)
   os.Exit(1)
}

在上面的代码中,我们调用的函数不会为延迟匿名函数提供执行的机会,因为程序将退出。os.Exit()

输出结果

如果我们使用go run main.go命令运行上面的代码,那么我们将在终端中得到以下输出。

Inside the main function
Program exited: status 1.

我们可能得到的另一个信号是我们在CTRL+C的帮助下终止进程

如何在 Golang 中处理信号

我们确实讨论了将信号传递给程序的不同方式。现在,让我们谈谈我们如何处理这些信号并在 Go 中处理它们。

为了优雅地处理这些信号,我们可以使用os.Signal类型的通道,该通道本质上是阻塞的。然后我们将使用该函数,在该函数中我们可以传递我们期望的不同类型的信号,例如os.Interruptsyscall.SIGTERMNotify()

示例 2

考虑下面显示的代码。

package main

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

func main() {
   sigChannel := make(chan os.Signal, 1)
   signal.Notify(sigChannel, os.Interrupt, syscall.SIGTERM)

   fmt.Println("Try pressing CTRL + C to handle the interrupt")

   select {
   case <-sigChannel:
      fmt.Println("The interrupt got handled")
      os.Exit(0)
   }
}

在上面的代码中,我们创建了一个容量为 1 的缓冲通道,然后我们调用了该Notify()函数。

输出结果

如果我们使用go run main.go命令运行上面的代码,然后按CTRL + C,那么我们将在终端中得到以下输出。

Try pressing CTRL + C to handle the interrupt
The interrupt got handled