golang信号通知 signal.Notify NotifyContext完整示例

在看示例之前有必要先看看Go程序中信号的默认行为,

go中信号的默认行为如下:

SIGHUP、SIGINT或SIGTERM信号会导致程序退出。SIGQUIT、SIGILL、SIGTRAP、SIGABRT、SIGSTKFLT、SIGEMT或SIGSYS信号会导致程序退出并进行堆栈转储。SIGTSTP、SIGTTIN或SIGTTOU信号获取系统默认行为(这些信号由shell用于作业控制)。SIGPROF信号由Go运行时直接处理以实现运行时。CPU配置文件。将捕捉到其他信号,但不会采取任何行动。

如果Go程序启动时忽略了SIGHUP或SIGINT(信号处理程序设置为SIG_IGN),它们将保持被忽略状态。

如果Go程序是用一个非空信号掩码启动的,那么这通常会得到遵守。然而,有些信号是明确取消阻塞的:同步信号SIGILL、SIGTRAP、SIGSTKFLT、SIGCHLD、SIGPROF,以及在Linux上的信号32(SIGCANCEL)和33(SIGSETXID)(SIGCANCEL和SIGSETXID由glibc内部使用)。操作系统启动的子进程。Exec或os/Exec将继承修改后的信号掩码。

信号通知使用示例:

Go 复制代码
package main

import (
	"context"
	"fmt"
	"log"
	"os"
	"os/signal"
)

// 中断信号演示,
// signal.Notify(c, os.Interrupt) 这里的第二个参数即为要中转的信号,如果没有这个参数,所有的信号都会被中转到c
func demoSigInterrupt() {

	c := make(chan os.Signal, 1)   //创建一个用来接收信号的管道 c
	signal.Notify(c, os.Interrupt) //将包中接收到的中断信号(os.Interrupt)转送给管道c; 当程序被ctrl+c中断时中断信号就会被转送给管c
	s := <-c                       // 从管道中读取信息并赋值给s;
	fmt.Println("Got signal:", s)  // Got signal: interrupt
}

// 中转所有信号
func demoSigAll() {
	c := make(chan os.Signal, 1)
	signal.Notify(c) // 不传第二个参数,将所有的OS信号都转送到c
	s := <-c
	fmt.Println("Got signal: ", s)
}

var neverRead = make(chan struct{})

// This example passes a context with a signal to tell a blocking function that
// it should abandon its work after a signal is received.
func demoNotifyContext() {
	// NotifyContext返回一份父上下文的拷贝, 当收到os.Interrupt信号或者stop函数被执行时, 这时这个上下文的通道就会被关闭
	ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
	defer stop()

	// 获取当前进程自己
	p, err := os.FindProcess(os.Getpid())
	if err != nil {
		log.Fatal(err)
	}

	// 在unix类的系统中,ctrl+c将发送一个SIGINT信号到执行中的程序
	// 注意下面这个代码仅在unix系统中生效, 可在文件顶部添加 //go:build unix 来指示仅unix系统才会被编译
	// 这里模拟先自己发送一个SIGINT中断信号
	if err := p.Signal(os.Interrupt); err != nil {
		log.Fatal(err)
	}

	// 处理多个管道模拟
	select {
	case <-neverRead:
		fmt.Println("这个不会被执行,因为它是空的,仅作为多管道模拟")
	case <-ctx.Done():
		fmt.Println(ctx.Err()) // prints "context canceled"
		stop()                 // stop receiving signal notifications as soon as possible.
	}

}
func main() {
	// demoSigInterrupt()
	// demoSigAll()
	demoNotifyContext()
	fmt.Println("main ended")
}
相关推荐
景天科技苑3 分钟前
【Rust宏编程】Rust有关宏编程底层原理解析与应用实战
开发语言·后端·rust·rust宏·宏编程·rust宏编程
yorushika_29 分钟前
python打卡训练营打卡记录day45
开发语言·python·深度学习·tensorboard
狠难说30 分钟前
Prometheus 中 Gauge 指标:特点、操作函数及最佳实践
后端
封奚泽优31 分钟前
使用Python进行函数作画
开发语言·python
aningxiaoxixi39 分钟前
JAVA之 Lambda
java·开发语言
只在空想家1 小时前
Servlet 体系结构
java·后端·servlet
ApiHug1 小时前
ApiHug 1.3.9 支持 Spring 3.5.0 + Plugin 0.7.4 内置小插件升级!儿童节快乐!!!
java·后端·spring·api·apihug·apismart
玛奇玛丶1 小时前
💥昨天掘金 Web 端突然登不上了,一次网络异常的排查记录
后端·负载均衡
南囝coding1 小时前
这款AI自动生成播客工具,必须收藏!
前端·后端
追逐时光者1 小时前
C#/.NET/.NET Core优秀项目和框架2025年5月简报
后端·.net