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将继承修改后的信号掩码。
 

信号通知使用示例:

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")
}

相关推荐

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

    2024-05-25 21:40:56       29 阅读
  2. golang通道(chan)选择(select)与关闭(close)使用示例

    2024-05-25 21:40:56       33 阅读
  3. Go-JWT完整示例

    2024-05-25 21:40:56       40 阅读
  4. golang定时器使用示例

    2024-05-25 21:40:56       45 阅读
  5. 23种设计模式-Golang完整版)

    2024-05-25 21:40:56       42 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-05-25 21:40:56       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-05-25 21:40:56       101 阅读
  3. 在Django里面运行非项目文件

    2024-05-25 21:40:56       82 阅读
  4. Python语言-面向对象

    2024-05-25 21:40:56       91 阅读

热门阅读

  1. sql日期函数统计日月年订单数

    2024-05-25 21:40:56       31 阅读
  2. MySQL之架构设计与历史(六)

    2024-05-25 21:40:56       36 阅读
  3. [数据集][图像分类]车辆分类数据集1600张10类别

    2024-05-25 21:40:56       36 阅读
  4. HTML5 本地存储与应用缓存

    2024-05-25 21:40:56       33 阅读
  5. memcpy的使⽤和模拟实现

    2024-05-25 21:40:56       36 阅读
  6. 通关!游戏设计之道Day14

    2024-05-25 21:40:56       36 阅读
  7. python 多线程处理图片

    2024-05-25 21:40:56       32 阅读
  8. unity 制作app实现底部导航栏和顶部状态栏

    2024-05-25 21:40:56       38 阅读
  9. 什么是js

    2024-05-25 21:40:56       31 阅读