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

攔截信號(hào)Golang應(yīng)用優(yōu)雅關(guān)閉的操作方法

 更新時(shí)間:2023年02月02日 10:45:59   作者:夢想畫家  
這篇文章主要介紹了攔截信號(hào)優(yōu)雅關(guān)閉Golang應(yīng)用,本文介紹了信號(hào)的概念及常用信號(hào),并給出了應(yīng)用廣泛的幾個(gè)示例,例如優(yōu)雅地關(guān)閉應(yīng)用服務(wù)、在命令行應(yīng)用中接收終止命令,需要的朋友可以參考下

Golang不是像C語言的系統(tǒng)級(jí)編程語言,但仍提供了以下特性幫助開發(fā)者與底層操作系統(tǒng)進(jìn)行交互,如信號(hào)(singals),os/singals包實(shí)現(xiàn)了這些功能。相對于其他語言處理OS信號(hào)采用復(fù)雜或冗余的方法,Golang內(nèi)置OS包提供了易用的方法處理Unix信號(hào),非常直接、簡單。事實(shí)上,類unix系統(tǒng)中通常處理singal是必要的,本文介紹singal概念,并通過示例說明其應(yīng)用場景。

從示例開始

假設(shè)場景:Golang應(yīng)用在關(guān)閉時(shí)打印消息:“Thank you for using Golang.” 首先新建main函數(shù),函數(shù)體模擬執(zhí)行一些業(yè)務(wù),直到接收到結(jié)束命令。

func main() {
   for {
      fmt.Println("Doing Work")
      time.Sleep(1 * time.Second)
   }
}

當(dāng)運(yùn)行應(yīng)用,然后從OS發(fā)送執(zhí)行kill信號(hào)(Ctrl + C),可能輸出結(jié)果類似這樣:

Doing Work
Doing Work
Doing Work
Process finished with exit code 2

現(xiàn)在我們希望攔截kill信號(hào)并定義處理邏輯:打印必要的關(guān)閉信息。

接收信號(hào)

首先創(chuàng)建channe接收來自操作系統(tǒng)的命令,os包提供了signal接口處理基于OS規(guī)范信號(hào)實(shí)現(xiàn)。

killSignal := make(chan os.Signal, 1)

為了通知killSignal,需使用signal包中提供的Notify函數(shù),第一個(gè)參數(shù)為Signal類型的channel,下一個(gè)參數(shù)接收一組發(fā)給通道的信號(hào)列表。

Notify(c chan<- os.Signal, sig ...os.Signal)

我們也可以使用syscall包通知特定命令的信號(hào):

signal.Notify(c chan<- os.Signal, syscall.SIGINT, syscall.SIGTERM)

為了處理信號(hào),我們在main函數(shù)中使用killSignal通道等待interrupt信號(hào),一旦接收到來自O(shè)S的命令,則打印結(jié)束消息并接收應(yīng)用?,F(xiàn)在把處理業(yè)務(wù)的循環(huán)代碼移入獨(dú)立的goroute中,這里定義一個(gè)匿名函數(shù):

go func() {
   for {
      fmt.Println("Doing Work")
      time.Sleep(1 * time.Second)
   }
}()

因?yàn)闃I(yè)務(wù)代碼運(yùn)行在獨(dú)立routine中,main函數(shù)實(shí)現(xiàn)等待killSignal信號(hào)并在結(jié)束之前打印消息。

<-killSignal
fmt.Println("Thanks for using Golang!")

完整代碼

下面把幾個(gè)部分組裝在一起,完整代碼如下:

package main

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

func main() {

	killSignal := make(chan os.Signal, 1)
	signal.Notify(killSignal, os.Interrupt)
	go func() {
		for {
			fmt.Println("Doing Work")
			time.Sleep(1 * time.Second)
		}
	}()
	<-killSignal
	fmt.Println("Thanks for using Golang!")
}

運(yùn)行程序,看到一直執(zhí)行業(yè)務(wù)循環(huán),直到接收到interrupt信號(hào),打印消息并結(jié)束:

Doing Work
Doing Work
Doing Work
Thanks for using Golang!

常見信號(hào)

對于命令行程序,當(dāng)按CTRL+C時(shí),會(huì)發(fā)送SIGINT信號(hào),SIGINT是與指定特定信號(hào)數(shù)字相關(guān)聯(lián)的名稱。信號(hào)實(shí)際是可以有程序生成的軟件中斷,也是一種異步處理事件機(jī)制。通常為了安全起見,信號(hào)采用名稱而不是數(shù)值生成。

大多數(shù)信號(hào)及其具體動(dòng)作都是由操作系統(tǒng)定義的,并還在操作系統(tǒng)權(quán)限范圍內(nèi)執(zhí)行相應(yīng)功能。因此能夠處理某些事件并不能讓用戶自由地使用系統(tǒng),有些信號(hào)即使生成了也會(huì)被操作系統(tǒng)忽略,而由操作系統(tǒng)決定程序允許處理哪些信號(hào)。

舉例,SIGKILL 和 SIGSTOP 信號(hào)也可以被捕獲、阻塞或忽略。因?yàn)檫@些信號(hào)對于保持操作系統(tǒng)功能的"健全"至關(guān)重要,在極端條件下為內(nèi)核和root用戶提供了停止進(jìn)程的方法。與SIGKILL相關(guān)聯(lián)的數(shù)字是9,Linux提供了kill命令發(fā)送SIGTERM信號(hào),終止正在運(yùn)行的程序??梢允褂胟ill -l命令查看完整的支持信號(hào):

圖片

有許多信號(hào)可用,但并非所有信號(hào)都能被程序處理。像SIGKILL和SIGSTOP這樣的信號(hào)既不能被程序調(diào)用,也不能被程序忽略。原因很簡單:它們太重要了,不允許被惡意程序?yàn)E用。

系統(tǒng)信號(hào)分為同步信號(hào)和異步信號(hào)。其中同步信號(hào)是程序執(zhí)行中的錯(cuò)誤觸發(fā)的信號(hào),如SIGBUS, SIGFPE, SIGSEGV,在 Golang 程序中,同步信號(hào)通常會(huì)被轉(zhuǎn)換為 runtime panic。同步信號(hào)需要事件及事件時(shí)間,相反異步信號(hào)不需要于時(shí)鐘同步,異步信號(hào)是系統(tǒng)內(nèi)核或其它程序發(fā)送的信號(hào)。舉例,SIGHUP表示它控制的終端被關(guān)閉,常用的是當(dāng)按CTRL+C時(shí),會(huì)發(fā)送SIGINT信號(hào)。當(dāng)SIGINT信號(hào)有鍵盤產(chǎn)生時(shí),實(shí)際上不是終止應(yīng)用程序,而是生成特定鍵盤中斷,并且處理該中斷的程序開始執(zhí)行,其缺省行為時(shí)關(guān)閉應(yīng)用程序,但我們可以覆蓋缺省行為,寫我們自己的業(yè)務(wù)處理邏輯。

事實(shí)上許多信號(hào)處理都可以被覆蓋,Go開發(fā)者可以編寫自己的處理程序來自定義信號(hào)處理行為。然而,除非有非常好的理由,否則改變信號(hào)的默認(rèn)行為并不是明智的想法。這里引用列舉常用linux信號(hào):

SIGHUP: ‘HUP’ = ‘hung up’. This signal is generated when a controlling process dies or hangs up detected on the controlling terminal.
SIGINT: When a process is interrupted from keyboard by pressing CTRL+C
SIGQUIT: Quit from keyboard
SIGILL: Illegal instruction. A synonym for SIGPWR() – power failure
SIGABRT: Program calls the abort() function – an emergency stop.
SIGBUS: Bad memory access. Attempt was made to access memory inappropriately
SIGFPE: FPE = Floating point exception
SIGKILL: The kill signal. The process was explicitly killed.
SIGUSR1: This signal is open for programmers to write a custom behavior.
SIGSEGV: Invalid memory reference. In C when we try to access memory beyond array limit, this signal is generated.
SIGUSR2: This signal is open for programmers to write a custom behavior.
SIGPIPE: This signals us open for programmers to write a custom behavior.
SIGALRM: Process requested a wake up call by the operating system such as by calling the alarm() function.
SIGTERM: A process is killed

處理多個(gè)信號(hào)

下面再看一個(gè)示例,較上面的示例增加了對SIGTERM信號(hào)的處理:

package main

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

func handler(signal os.Signal) {
	if signal == syscall.SIGTERM {
		fmt.Println("Got kill signal. ")
		fmt.Println("Program will terminate now.")
		os.Exit(0)
	} else if signal == syscall.SIGINT {
		fmt.Println("Got CTRL+C signal")
		fmt.Println("Closing.")
		os.Exit(0)
	} else {
		fmt.Println("Ignoring signal: ", signal)
	}
}

func main() {
	sigchnl := make(chan os.Signal, 1)
	signal.Notify(sigchnl)
    // signal.Notify(sigchnl, os.Interrupt, syscall.SIGTERM)
	exitchnl := make(chan int)

	go func() {
		for {
			s := <-sigchnl
			handler(s)
		}
	}()

	exitcode := <-exitchnl
	os.Exit(exitcode)
}

首先創(chuàng)建通道接收響應(yīng)信號(hào),我們也可以指定信號(hào)類型:signal.Notify(sigchnl, os.Interrupt, syscall.SIGTERM),否則會(huì)接收所有信號(hào),包括命令窗口改變大小信號(hào)。然后在handle函數(shù)判斷信號(hào)類型并分別進(jìn)行處理。

程序運(yùn)行后,linux可以通過ps -h 查看go程序,然后執(zhí)行kill命令。

NotifyContext示例

Go.1.16提供了signal.NotifyContext函數(shù),可以實(shí)現(xiàn)更優(yōu)雅的關(guān)閉功能。下面示例實(shí)現(xiàn)簡單web服務(wù)器,示例handle需要10s處理時(shí)間,如果正在運(yùn)行的web服務(wù),客戶端通過postman或cURL發(fā)送請求,然后在服務(wù)端立刻通過ctrl+C發(fā)送終止信號(hào)。
我們希望看到服務(wù)器在終止之前通過響應(yīng)終止請求而優(yōu)雅地關(guān)閉。如果關(guān)閉時(shí)間過長,可以發(fā)送另一個(gè)中斷信號(hào)立即退出,或者暫停將在5秒后開始。

package main

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

var (
	server http.Server
)

func main() {
	// Create context that listens for the interrupt signal from the OS.
	ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
	defer stop()

	server = http.Server{
		Addr: ":8080",
	}

	// Perform application startup.
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		time.Sleep(time.Second * 10)
		fmt.Fprint(w, "Hello world!")
	})

	// Listen on a different Goroutine so the application doesn't stop here.
	go server.ListenAndServe()

	// Listen for the interrupt signal.
	<-ctx.Done()

	// Restore default behavior on the interrupt signal and notify user of shutdown.
	stop()
	fmt.Println("shutting down gracefully, press Ctrl+C again to force")

	// Perform application shutdown with a maximum timeout of 5 seconds.
	timeoutCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	if err := server.Shutdown(timeoutCtx); err != nil {
		fmt.Println(err)
	}
}

總結(jié)

本文介紹了信號(hào)的概念及常用信號(hào),并給出了應(yīng)用廣泛的幾個(gè)示例,例如優(yōu)雅地關(guān)閉應(yīng)用服務(wù)、在命令行應(yīng)用中接收終止命令。

到此這篇關(guān)于攔截信號(hào)Golang應(yīng)用優(yōu)雅關(guān)閉的文章就介紹到這了,更多相關(guān)Golang關(guān)閉內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 一文詳解Golang中的基礎(chǔ)語法

    一文詳解Golang中的基礎(chǔ)語法

    這篇文章主要為大家詳細(xì)介紹了Golang中基礎(chǔ)語法的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)Golang有一定的幫助,感興趣的可以了解一下
    2023-03-03
  • Golang?流水線設(shè)計(jì)模式實(shí)踐示例詳解

    Golang?流水線設(shè)計(jì)模式實(shí)踐示例詳解

    這篇文章主要為大家介紹了Golang?流水線設(shè)計(jì)模式實(shí)踐示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • Linux操作系統(tǒng)上打包Go項(xiàng)目實(shí)現(xiàn)方式

    Linux操作系統(tǒng)上打包Go項(xiàng)目實(shí)現(xiàn)方式

    文章介紹了Go項(xiàng)目依賴打包的兩種方法:GoModules(管理依賴并確保一致性)和靜態(tài)鏈接(嵌入依賴生成獨(dú)立可執(zhí)行文件),需注意cgo配置及系統(tǒng)兼容性,推薦根據(jù)需求選擇合適方式
    2025-08-08
  • Golang垃圾回收器執(zhí)行鏈路詳細(xì)分析

    Golang垃圾回收器執(zhí)行鏈路詳細(xì)分析

    垃圾回收簡稱GC,就是對程序中不再使用的內(nèi)存資源進(jìn)行自動(dòng)回收釋放的操作,這篇文章主要介紹了Golang垃圾回收器執(zhí)行鏈路詳細(xì)分析的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-12-12
  • Go語言遞歸函數(shù)的具體實(shí)現(xiàn)

    Go語言遞歸函數(shù)的具體實(shí)現(xiàn)

    本文主要介紹了Go語言遞歸函數(shù)的具體實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • Go語言提升開發(fā)效率的語法糖技巧分享

    Go語言提升開發(fā)效率的語法糖技巧分享

    每門語言都有自己的語法糖,像java的語法糖就有方法變長參數(shù)、拆箱與裝箱、枚舉、for-each等等,Go語言也不例外。本文就來介紹一些Go語言的語法糖,需要的可以參考一下
    2022-07-07
  • go語言中數(shù)據(jù)接口set集合的實(shí)現(xiàn)

    go語言中數(shù)據(jù)接口set集合的實(shí)現(xiàn)

    set集合是一種常見的數(shù)據(jù)結(jié)構(gòu),它代表了一個(gè)唯一元素的集合,本文主要介紹了set的基本特性,包括唯一性、無序性、可變性和集合運(yùn)算,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-10-10
  • go?zero微服務(wù)實(shí)戰(zhàn)處理每秒上萬次的下單請求

    go?zero微服務(wù)實(shí)戰(zhàn)處理每秒上萬次的下單請求

    這篇文章主要為大家介紹了go?zero微服務(wù)實(shí)戰(zhàn)處理每秒上萬次的下單請求示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • 詳解Go語言如何實(shí)現(xiàn)并發(fā)安全的map

    詳解Go語言如何實(shí)現(xiàn)并發(fā)安全的map

    go語言提供的數(shù)據(jù)類型中,只有channel是并發(fā)安全的,基礎(chǔ)map并不是并發(fā)安全的,本文為大家整理了三種實(shí)現(xiàn)了并發(fā)安全的map的方案,有需要的可以參考下
    2023-12-12
  • Go??import _ 下劃線使用

    Go??import _ 下劃線使用

    這篇文章主要為大家介紹了Go??import下劃線_使用小技巧,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12

最新評(píng)論

甘孜县| 晋中市| 夏津县| 灌阳县| 泾川县| 桃江县| 靖宇县| 革吉县| 五华县| 桦川县| 临洮县| 鄢陵县| 子长县| 营口市| 盐亭县| 阿克陶县| 吉安市| 桐梓县| 宁夏| 洛阳市| 措美县| 金秀| 句容市| 博白县| 丹凤县| 吉隆县| 嘉义市| 丽江市| 敦煌市| 武宁县| 洛阳市| 盐津县| 大荔县| 内丘县| 大田县| 宜川县| 涟水县| 南投市| 朝阳县| 阳朔县| 贡嘎县|