最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Golang信號處理實戰(zhàn)

 更新時間:2025年12月24日 11:23:46   作者:言之。  
本文介紹了Go語言中os/signal包的基本用法,用于處理Unix系統(tǒng)中的異步信號,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

1. 為什么需要信號處理

在類 Unix 系統(tǒng)中,信號(Signal)是一種異步通知機制,內(nèi)核通過它告訴進程發(fā)生了某種事件,比如:

  • 終止進程SIGTERM(kill 發(fā)送的默認(rèn)信號)、SIGINT(Ctrl+C)
  • 掛起/恢復(fù)SIGTSTP(Ctrl+Z)
  • 重新加載配置SIGHUP
  • 自定義信號SIGUSR1、SIGUSR2

如果不處理,進程會使用 默認(rèn)行為(可能直接退出)。
os/signal 包讓我們在用戶態(tài)捕獲這些信號,并執(zhí)行自定義邏輯(比如優(yōu)雅退出、保存狀態(tài)、重載配置等)。

2. 核心 API

函數(shù)功能常見用途
Notify(c chan<- os.Signal, sig ...os.Signal)將指定信號轉(zhuǎn)發(fā)到 c訂閱信號
Stop(c chan<- os.Signal)停止向 c 轉(zhuǎn)發(fā)信號取消訂閱
Ignore(sig ...os.Signal)忽略信號(不再轉(zhuǎn)發(fā)給程序)屏蔽特定信號
Reset(sig ...os.Signal)恢復(fù)信號默認(rèn)行為信號處理恢復(fù)默認(rèn)
NotifyContext(ctx, sig...)返回會在收到信號時自動 cancel 的 Context優(yōu)雅退出

3. 基本使用

示例:監(jiān)聽SIGINT(Ctrl+C)和SIGTERM(kill)

package main

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

func main() {
	sigChan := make(chan os.Signal, 1)

	// 訂閱兩個信號
	signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)

	fmt.Println("程序啟動,等待信號...")

	sig := <-sigChan // 阻塞等待
	fmt.Println("收到信號:", sig)

	fmt.Println("執(zhí)行清理邏輯...")
	// 這里做關(guān)閉文件、斷開連接等操作

	fmt.Println("程序退出")
}

運行:

go run main.go
# Ctrl+C 或 kill PID 會觸發(fā)信號

4. 使用NotifyContext優(yōu)雅退出

Go 1.16+ 引入的 NotifyContext 結(jié)合 context 讓信號處理更簡潔。

package main

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

func main() {
	ctx, stop := signal.NotifyContext(context.Background(),
		syscall.SIGINT, syscall.SIGTERM)
	defer stop()

	fmt.Println("程序啟動,等待信號...")

	// 模擬業(yè)務(wù)協(xié)程
	go func() {
		for {
			select {
			case <-ctx.Done():
				fmt.Println("業(yè)務(wù)收到退出信號,清理中...")
				time.Sleep(1 * time.Second)
				fmt.Println("業(yè)務(wù)清理完成")
				return
			default:
				fmt.Println("業(yè)務(wù)運行中...")
				time.Sleep(2 * time.Second)
			}
		}
	}()

	<-ctx.Done() // 阻塞,直到信號觸發(fā)
	fmt.Println("主程序退出")
}

好處:

  • 自動取消 context
  • 不用自己建 channel
  • 多個 goroutine 可同時感知退出

5. 高級用法

5.1 忽略信號

signal.Ignore(syscall.SIGPIPE) // 忽略管道斷開

5.2 動態(tài)取消訂閱

signal.Stop(sigChan) // 取消 channel 的訂閱

5.3 同時監(jiān)聽多個信號

signal.Notify(sigChan) // 不指定信號時,監(jiān)聽所有信號

不推薦監(jiān)聽全部信號,可能會攔截 SIGKILL、SIGSTOP 等無法處理的信號。

6. 原理機制

簡化版流程:

  1. Notify 注冊信號 → 調(diào)用 runtime 的 enableSignal(n)。
  2. runtime 捕獲信號后調(diào)用 process()。
  3. process 遍歷所有 channel handler,非阻塞發(fā)送信號。
  4. Stop 時調(diào)用 disableSignal(n),等待 runtime 信號隊列清空(signalWaitUntilIdle())。

特點:

  • 非阻塞投遞:channel 必須有緩沖,否則可能丟信號。
  • 引用計數(shù):多個 channel 可監(jiān)聽同一信號,ref=0 時才會真正停止捕獲。
  • bitmask 存儲:handler 用 bit 位記錄關(guān)注的信號,內(nèi)存占用小。

7. 最佳實踐

  1. 總是用緩沖 channel

    make(chan os.Signal, 1)
    

    避免信號丟失。

  2. 優(yōu)雅退出而不是強殺
    SIGTERM 里做清理,配合 context 實現(xiàn)安全收尾。

  3. 避免監(jiān)聽全部信號
    只訂閱需要的信號,避免影響系統(tǒng)默認(rèn)行為。

  4. 多 goroutine 協(xié)同
    NotifyContext 讓所有協(xié)程通過 <-ctx.Done() 感知退出。

  5. 容器化部署必備
    Docker 默認(rèn)用 SIGTERM 停止容器,業(yè)務(wù)代碼應(yīng)處理此信號。

8. 實戰(zhàn)案例:優(yōu)雅關(guān)閉 HTTP 服務(wù)器

package main

import (
	"context"
	"fmt"
	"net/http"
	"os/signal"
	"syscall"
	"time"
)

func main() {
	srv := &http.Server{Addr: ":8080"}

	// 啟動 HTTP 服務(wù)
	go func() {
		fmt.Println("HTTP 服務(wù)啟動在 :8080")
		if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			fmt.Println("HTTP 服務(wù)器出錯:", err)
		}
	}()

	// 信號監(jiān)聽
	ctx, stop := signal.NotifyContext(context.Background(),
		syscall.SIGINT, syscall.SIGTERM)
	defer stop()

	<-ctx.Done() // 等待信號
	fmt.Println("收到退出信號,正在關(guān)閉服務(wù)器...")

	// 設(shè)置超時的優(yōu)雅關(guān)閉
	shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	if err := srv.Shutdown(shutdownCtx); err != nil {
		fmt.Println("服務(wù)器關(guān)閉錯誤:", err)
	}

	fmt.Println("服務(wù)器已優(yōu)雅退出")
}

這樣寫的好處:

  • 支持 Ctrl+C / kill
  • 容器化部署時能優(yōu)雅退出
  • 確保連接處理完成后再關(guān)閉

到此這篇關(guān)于Golang信號處理實戰(zhàn)的文章就介紹到這了,更多相關(guān)Golang信號處理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • golang socket斷點續(xù)傳大文件的實現(xiàn)方法

    golang socket斷點續(xù)傳大文件的實現(xiàn)方法

    今天小編就為大家分享一篇golang socket斷點續(xù)傳大文件的實現(xiàn)方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-07-07
  • Go 協(xié)程超時控制的實現(xiàn)

    Go 協(xié)程超時控制的實現(xiàn)

    本文主要介紹了Go 協(xié)程超時控制的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • Go語言中排序的3種實現(xiàn)方法

    Go語言中排序的3種實現(xiàn)方法

    在寫代碼過程中,排序是經(jīng)常會遇到的需求,這篇文章主要為大家介紹三種常用的方法,文中的示例代碼簡潔易懂,需要的小伙伴可以參考下
    2023-08-08
  • GO如何模擬流操作實現(xiàn)示例探究

    GO如何模擬流操作實現(xiàn)示例探究

    這篇文章主要為大家介紹了GO如何模擬流操作實現(xiàn)示例探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2024-01-01
  • Go語言開發(fā)快速學(xué)習(xí)CGO編程

    Go語言開發(fā)快速學(xué)習(xí)CGO編程

    這篇文章主要為大家介紹了Go語言開發(fā)之快速學(xué)習(xí)CGO編程,看了本文你就會發(fā)現(xiàn)CGO編程其實沒有想象的那么難,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-04-04
  • golang?recover函數(shù)使用中的一些坑解析

    golang?recover函數(shù)使用中的一些坑解析

    這篇文章主要為大家介紹了golang?recover函數(shù)使用中的一些坑解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-02-02
  • Go語言之ORM(對象關(guān)系映射)庫詳解

    Go語言之ORM(對象關(guān)系映射)庫詳解

    GORM是Go語言流行ORM庫,支持多數(shù)據(jù)庫與結(jié)構(gòu)體映射表,具備鏈?zhǔn)紸PI、自動遷移、關(guān)聯(lián)操作等功能,原倉庫已歸檔,推薦使用GORMv2,性能優(yōu)化且API更清晰,適合快速開發(fā),不適用于性能極致需求
    2025-07-07
  • Go語言題解LeetCode463島嶼的周長示例詳解

    Go語言題解LeetCode463島嶼的周長示例詳解

    這篇文章主要為大家介紹了Go語言題解LeetCode463島嶼的周長示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-12-12
  • Golang中深拷貝與淺拷貝詳解

    Golang中深拷貝與淺拷貝詳解

    這篇文章主要為大家詳細(xì)介紹一下Golang深拷貝和淺拷貝,文中有詳細(xì)的代碼示例供大家參考,需要的可以參考一下
    2023-05-05
  • Golang匯編命令解讀及使用

    Golang匯編命令解讀及使用

    這篇文章主要介紹了Golang匯編命令解讀及命令使用,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-04-04

最新評論

江安县| 临江市| 南康市| 阿拉尔市| 渝中区| 海原县| 图们市| 灵璧县| 兰考县| 桐柏县| 钟祥市| 沈丘县| 孝昌县| 张家界市| 电白县| 舞钢市| 永修县| 平陆县| 沛县| 包头市| 塘沽区| 漾濞| 普兰县| 沂水县| 克什克腾旗| 和龙市| 玛曲县| 施甸县| 文登市| 北京市| 台山市| 长治县| 班戈县| 乐业县| 杭州市| 黄平县| 张家港市| 陇西县| 北流市| 旅游| 内黄县|