溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Go語言開發(fā)(十三)、Go語言常用標(biāo)準(zhǔn)庫三

發(fā)布時(shí)間:2020-07-12 19:10:50 來源:網(wǎng)絡(luò) 閱讀:815 作者:天山老妖S 欄目:編程語言

Go語言開發(fā)(十三)、Go語言常用標(biāo)準(zhǔn)庫三

一、sync

1、sync簡(jiǎn)介

sync提供基本的同步原語,如sync.Mutex,sync.RWMutex,sync.Once,sync.Cond,sync.Waitgroup,除了Once和WaitGroup類型外,大多數(shù)類型都供低級(jí)庫使用。Go語言中,不要通過共享內(nèi)存通信,而要通過通信共享內(nèi)存,通過Channel和溝通可以更好地完成更高級(jí)別的同步。

type Locker interface {
   Lock()
   Unlock()
}

Locker提供了鎖的兩個(gè)操作方法,Lock、Unlock。

2、sync.Mutex

sync.Mutex是互斥鎖,是Locker的一種實(shí)現(xiàn)。
一個(gè)互斥鎖只能同時(shí)被一個(gè)goroutine鎖定,其它goroutine將阻塞直到互斥鎖被解鎖(重新爭(zhēng)搶對(duì)互斥鎖的鎖定)。
sync.Mutex使用注意:
(1)在首次使用后不要復(fù)制互斥鎖。
(2)對(duì)一個(gè)未鎖定的互斥鎖解鎖將會(huì)產(chǎn)生運(yùn)行時(shí)錯(cuò)誤。
使用示例:

package main

import (
   "fmt"
   "sync"
   "time"
)

var locker sync.Mutex

func mutexDemo() {
   var value int = 0
   for i := 0; i < 100; i++ {
      go func(i int) {
         locker.Lock()
         defer locker.Unlock()
         fmt.Printf("Goroutine %d : value: %d\n", i, value)
         value++
      }(i)
   }
}
func main() {
   mutexDemo()
   time.Sleep(time.Second)
}

3、sync.Pool

sync.Pool?臨時(shí)對(duì)象池用于存儲(chǔ)臨時(shí)對(duì)象,將使用完畢的對(duì)象存入對(duì)象池中,在需要的時(shí)候取出來重復(fù)使用,目的是為了避免重復(fù)創(chuàng)建相同的對(duì)象造成GC負(fù)擔(dān)過重。如果對(duì)象不再被其它變量引用,存放的臨時(shí)對(duì)象可能會(huì)被GC回收掉。

type Pool struct {
   // 創(chuàng)建臨時(shí)對(duì)象的函數(shù)
   New func() interface{}
}

// 向臨時(shí)對(duì)象池中存入對(duì)象
func (p *Pool) Put(x interface{})

// 從臨時(shí)對(duì)象池中取出對(duì)象
func (p *Pool) Get() interface{}

從sync.Pool中取出對(duì)象時(shí),如果Pool中沒有對(duì)象,將返回nil,但如果給 Pool.New字段指定一個(gè)函數(shù),Pool將使用指定函數(shù)創(chuàng)建一個(gè)新對(duì)象返回。
sync.Pool可以安全的在多個(gè)goroutine中并行使用,但并不適用于所有空閑對(duì)象,應(yīng)該用來管理并發(fā)的例程共享的臨時(shí)對(duì)象,而不應(yīng)該管理短壽命對(duì)象中的臨時(shí)對(duì)象。
sync.Pool使用示例如下:

package main

import (
   "bytes"
   "io"
   "os"
   "sync"
   "time"
)

var bufPool = sync.Pool{
   New: func() interface{} {
      return new(bytes.Buffer)
   },
}

func Log(w io.Writer, key, val string) {
   // 獲取臨時(shí)對(duì)象,沒有則自動(dòng)創(chuàng)建
   b := bufPool.Get().(*bytes.Buffer)
   b.Reset()
   b.WriteString(time.Now().Format(time.RFC3339))
   b.WriteByte(' ')
   b.WriteString(key)
   b.WriteByte('=')
   b.WriteString(val)
   w.Write(b.Bytes())
   // 將臨時(shí)對(duì)象放回到Pool中
   bufPool.Put(b)
}

func main() {
   Log(os.Stdout, "key", "value")
}

// output:
// 2018-12-31T15:57:27+08:00 key=value

4、sync.Once

sync.Once可以使得函數(shù)多次調(diào)用只執(zhí)行一次。

type Once struct {
   m    Mutex
   done uint32
}
func (o *Once) Do(f func()) 

用done來記錄執(zhí)行次數(shù),用互斥鎖m來保證僅被執(zhí)行一次。只有一個(gè)Do方法,調(diào)用執(zhí)行。
利用sync.Once實(shí)現(xiàn)單例模式代碼如下:

package Singleton

import (
   "sync"
)

type Singleton map[string]string

var (
   instance Singleton
   once sync.Once
)

func New() Singleton{
   once.Do(func() {
      instance = make(Singleton)
   })
   return instance
}

使用示例如下:

package main

import (
   "fmt"
   "DesignPattern/Singleton"
)

func main() {
   instance1 := Singleton.New()
   instance1["name"] = "Jack Bauer"
   instance2 := Singleton.New()
   fmt.Println("My name is", instance2["name"])
}
// output:
// My name is Jack Bauer

5、sync.RWMutex

sync.RWMutex是針對(duì)讀寫操作的互斥鎖,讀寫鎖與互斥鎖最大的不同就是可以分別對(duì)讀、寫進(jìn)行鎖定。一般用在大量讀操作、少量寫操作的情況。sync.RWMutex提供四種操作方法:

func (rw *RWMutex) Lock()
func (rw *RWMutex) Unlock()

func (rw *RWMutex) RLock()
func (rw *RWMutex) RUnlock()

RLock對(duì)讀操作進(jìn)行鎖定,RUnlock對(duì)讀鎖定進(jìn)行解鎖,Lock對(duì)寫操作進(jìn)行鎖定,Unlock對(duì)寫鎖定進(jìn)行解鎖。
sync.RWMutex鎖定規(guī)則如下:
(1)同時(shí)只能有一個(gè)goroutine能夠獲得寫鎖定。
(2)同時(shí)可以有任意多個(gè)gorouinte獲得讀鎖定。
(3)同時(shí)只能存在寫鎖定或讀鎖定(讀和寫互斥)。
(4)當(dāng)有一個(gè)goroutine獲得寫鎖定,其它無論是讀鎖定還是寫鎖定都將阻塞直到寫解鎖;當(dāng)有一個(gè)goroutine獲得讀鎖定,其它讀鎖定任然可以繼續(xù);當(dāng)有一個(gè)或任意多個(gè)讀鎖定,寫鎖定將等待所有讀鎖定解鎖后才能夠進(jìn)行寫鎖定。
sync.RWMutex讀寫鎖使用注意:
(1)在首次使用之后,不要復(fù)制讀寫鎖。
(2)不要混用鎖定和解鎖,如:Lock和RUnlock、RLock和Unlock。對(duì)未讀鎖定的讀寫鎖進(jìn)行讀解鎖或?qū)ξ磳戞i定的讀寫鎖進(jìn)行寫解鎖將會(huì)引起運(yùn)行時(shí)錯(cuò)誤。
使用示例代碼:

package main

import (
   "fmt"
   "sync"
   "time"
)

var rw sync.RWMutex

func RWMutexDemo() {
   var value int = 0
   for i := 0; i < 10; i++ {
      go func(i int) {
         rw.Lock()
         defer rw.Unlock()
         fmt.Printf("Goroutine %d : Write value: %d\n", i, value)
         value++
      }(i)
      go func(i int) {
         rw.RLock()
         defer rw.RUnlock()
         fmt.Printf("Goroutine %d : Read value: %d\n", i, value)
      }(i)

   }
}
func main() {
   RWMutexDemo()
   time.Sleep(time.Minute)
}

6、sync.WaitGroup

sync.WaitGroup用于等待一組goroutine結(jié)束。
sync.WaitGroup操作方法如下:

func (wg *WaitGroup) Add(delta int)
func (wg *WaitGroup) Done()
func (wg *WaitGroup) Wait()

Add用來添加goroutine的個(gè)數(shù)。Done執(zhí)行一次數(shù)量減1。Wait用來等待結(jié)束。
sync.WaitGroup使用示例如下:

package main

import (
   "fmt"
   "sync"
)

var wg sync.WaitGroup

func WaitGroupDemo() {
   var value int = 0
   for i := 0; i < 10; i++ {
      wg.Add(1)
      go func(i int) {
         defer wg.Done()
         fmt.Printf("Goroutine %d : Write value: %d\n", i, value)
         value++

      }(i)
      wg.Add(1)
      go func(i int) {
         defer wg.Done()
         fmt.Printf("Goroutine %d : Read value: %d\n", i, value)
      }(i)
   }
}

func main() {
   WaitGroupDemo()
   wg.Wait()
}

7、sync.Cond

sync.Cond實(shí)現(xiàn)一個(gè)條件等待變量,即等待或宣布事件發(fā)生的goroutine的會(huì)合點(diǎn)。

func NewCond(l Locker) *Cond
func (c *Cond) Broadcast()
func (c *Cond) Signal()
func (c *Cond) Wait()

NewCond用于根據(jù)Locker創(chuàng)建一個(gè)條件等待變量,Wait用于讓一個(gè)goroutine等待通知,Signal用于單次發(fā)送通知讓等待的goroutine繼續(xù),Broadcast用于廣播通知讓所有等待的goroutine繼續(xù)。
sync.Cond條件等待變量實(shí)現(xiàn)生產(chǎn)者-消費(fèi)者模式示例如下:

package main

import (
   "fmt"
   "math/rand"
   "sync"
   "time"
)

var locker = new(sync.Mutex)
var cond = sync.NewCond(locker)

var capacity = 10
var consumerNum = 5
var producerNum = 2

func Produce(out chan<- int) {
   for i := 0; i < producerNum; i++ {
      go func(nu int) {
         for {
            cond.L.Lock()
            for len(out) == capacity {
               fmt.Println("Capacity Full, stop Produce")
               cond.Wait()
            }
            num := rand.Intn(100)
            out <- num
            fmt.Printf("Producer %d produce: num %d\n", nu, num)
            cond.L.Unlock()
            cond.Signal()
            time.Sleep(time.Microsecond * 500)
         }
      }(i)
   }
}

func Consume(in <-chan int) {
   for i := 0; i < consumerNum; i++ {
      go func(nu int) {
         for {
            cond.L.Lock()
            for len(in) == 0 {
               fmt.Println("Capacity Empty, stop Consume")
               cond.Wait()
            }
            num := <-in
            fmt.Printf("Consumer %d: consume num %d\n", nu, num)
            cond.L.Unlock()
            time.Sleep(time.Second)
            cond.Signal()
         }
      }(i)
   }
}

func main() {
   rand.Seed(time.Now().UnixNano())

   quit := make(chan bool)
   ProductPool := make(chan int, capacity)

   Produce(ProductPool)
   Consume(ProductPool)

   <-quit
}

二、reflect

1、reflect簡(jiǎn)介

在計(jì)算機(jī)科學(xué)領(lǐng)域,反射是指能夠自描述和自控制的應(yīng)用。反射通過采用某種機(jī)制來實(shí)現(xiàn)對(duì)自己行為的描述(self-representation)和監(jiān)測(cè)(examination),并能根據(jù)自身行為的狀態(tài)和結(jié)果,調(diào)整或修改應(yīng)用所描述行為的狀態(tài)和相關(guān)的語義。
每種語言的反射模型都不同,并且某些語言不支持反射。Golang語言通過reflect包實(shí)現(xiàn)反射機(jī)制,在運(yùn)行時(shí)動(dòng)態(tài)的調(diào)用對(duì)象的方法和屬性。
Go語言中的變量包括(type, value)兩部分,type包括static type和concrete type。static typ是編碼時(shí)的類型(如int、string),concrete type是runtime的類型。
類型斷言能否成功,取決于變量的concrete type,而不是static type。因此,一個(gè)reader變量如果其concrete type實(shí)現(xiàn)了write方法,也可以被類型斷言為writer。
Golang指定類型變量的類型是靜態(tài)類型,在創(chuàng)建變量時(shí)類型就已經(jīng)確定,因此,反射主要與Golang的interface類型相關(guān)(type是concrete type)。
在Golang的實(shí)現(xiàn)中,每個(gè)interface變量都有一個(gè)(value, type)對(duì)用于記錄變量的實(shí)際值和類型。value是變量的實(shí)際值,type是變量的實(shí)際類型。interface類型的變量包含2個(gè)指針,一個(gè)指針指向值的類型(concrete type),另一個(gè)指針指向?qū)嶋H的值(value)。

2、reflect接口

func TypeOf(i interface{}) Type
TypeOf用來動(dòng)態(tài)獲取輸入?yún)?shù)接口中的值的類型,如果接口為空則返回nil。
func ValueOf(i interface{}) Value
ValueOf用來獲取輸入?yún)?shù)接口中的數(shù)據(jù)的值,如果接口為空則返回0。
reflect.ValueOf(interface)得到一個(gè)relfect.Value變量,可以通過relfect.Value本身的Interface()方法獲得接口變量的真實(shí)內(nèi)容,然后可以通過類型判斷進(jìn)行轉(zhuǎn)換,轉(zhuǎn)換為原有真實(shí)類型。真實(shí)類型可能是已知原有類型,也可能是未知原有類型。
對(duì)于已知原有類型:

package main

import (
   "fmt"
   "reflect"
)

func main() {

   var num float64 = 3.14
   value := reflect.ValueOf(num)
   pointer := reflect.ValueOf(&num)
   fmt.Println("value: ", value.Interface().(float64))
   fmt.Println("value: ", pointer.Interface().(*float64))
   fmt.Println("type: ", reflect.TypeOf(num))
}

// output:
// value:  3.14
// value:  0xc42001e0e8
// type:  float64

對(duì)于未知原有類型,需要進(jìn)行遍歷探測(cè)其Filed:

package main

import (
   "fmt"
   "reflect"
)

type Student struct {
   Name string
   ID   int
   Age  int
}

func (student Student) Print() {
   fmt.Printf("%s's ID is %d, %d years.", student.Name, student.ID, student.Age)
}

func handleFieldAndMethod(input interface{}) {
   inputType := reflect.TypeOf(input)
   fmt.Println("type: ", inputType.Name())
   inputValue := reflect.ValueOf(input)
   fmt.Println("value: ", inputValue)
   // 獲取方法字段
   // 1. 先獲取interface的reflect.Type,然后通過NumField進(jìn)行遍歷
   // 2. 再通過reflect.Type的Field獲取其Field
   // 3. 最后通過Field的Interface()得到對(duì)應(yīng)的value
   for i := 0; i < inputType.NumField(); i++ {
      field := inputType.Field(i)
      value := inputValue.Field(i).Interface()
      fmt.Printf("%s %v %v\n", field.Name, field.Type, value)
   }
   // 獲取方法
   // 1. 先獲取interface的reflect.Type,然后通過.NumMethod進(jìn)行遍歷
   for i := 0; i < inputType.NumMethod(); i++ {
      m := inputType.Method(i)
      fmt.Printf("%s: %v\n", m.Name, m.Type)
   }
}

func main() {

   bauer := Student{"Bauer", 1, 130}
   handleFieldAndMethod(bauer)
}

// output:
// type:  Student
// value:  {Bauer 1 130}
// Name string Bauer
// ID int 1
// Age int 130
// Print: func(main.Student)

func (v Value) MethodByName(name string) Value
MethodByName返回一個(gè)函數(shù)值對(duì)應(yīng)的reflect.Value方法的名字。
func (v Value) Call(in []Value) []Value
Call方法將最終調(diào)用真實(shí)的方法,參數(shù)必須一致。

package main

import (
   "fmt"
   "reflect"
)

type Student struct {
   Name string
   ID   int
   Age  int
}

func (student Student) Print() {
   fmt.Printf("%s's ID is %d, %d years.", student.Name, student.ID, student.Age)
}

func CallMethod() {
   student := Student{"Bauer", 1, 20}
   value := reflect.ValueOf(student)
   methodValue := value.MethodByName("Print")
   // 對(duì)于無參函數(shù)
   args := make([]reflect.Value, 0)
   methodValue.Call(args)
}

func main() {
   CallMethod()
}

// output:
// Print: func(main.Student)

三、runtime

1、runtime簡(jiǎn)介

Go語言編譯器產(chǎn)生本地可執(zhí)行代碼,可執(zhí)行代碼仍舊運(yùn)行在Go的 runtime中,runtime負(fù)責(zé)管理包括內(nèi)存分配、垃圾回收、棧處理、goroutine、channel、切片(slice)、map 和反射(reflection)等。
runtime與C標(biāo)準(zhǔn)庫的作用一樣都是為了語言的跨平臺(tái)性,runtime可以運(yùn)行在Windows和Unix平臺(tái),可以運(yùn)行在Intel或ARM處理器上。Go程序都附帶runtime,runtime負(fù)責(zé)與底層操作系統(tǒng)交互。

2、runtime常用方法

runtime.Gosched()
讓當(dāng)前goroutine讓出?cpu?以讓其它goroutine運(yùn)行,不會(huì)掛起當(dāng)前線程,因此當(dāng)前線程未來會(huì)繼續(xù)執(zhí)行。
func NumCPU() int
獲取當(dāng)前系統(tǒng)的邏輯CPU?核數(shù)量
runtime.GOMAXPROCS(i int)
設(shè)置最大的可同時(shí)使用的?CPU
通過runtime.GOMAXPROCS函數(shù),應(yīng)用程序何以在運(yùn)行期間設(shè)置運(yùn)行時(shí)系統(tǒng)中得邏輯處理器P最大數(shù)量。應(yīng)在應(yīng)用程序最早的調(diào)用。并且最好的設(shè)置P最大值的方法是在運(yùn)行Go程序之前設(shè)置好操作程序的環(huán)境變量GOMAXPROCS,而不是在程序中調(diào)用runtime.GOMAXPROCS函數(shù)。
無論傳遞給函數(shù)的整數(shù)值是什么值,運(yùn)行時(shí)系統(tǒng)的P最大值總會(huì)在1~256之間。
runtime.Goexit()
退出當(dāng)前?goroutine(但defer語句會(huì)照常執(zhí)行)
runtime.Goexit函數(shù)被調(diào)用后,會(huì)立即使調(diào)用他的Groution的運(yùn)行被終止,但其他Goroutine并不會(huì)受到影響。runtime.Goexit函數(shù)在終止調(diào)用它的Goroutine的運(yùn)行之前會(huì)先執(zhí)行該Groution中還沒有執(zhí)行的defer語句。
runtime.NumGoroutine()
獲取正在執(zhí)行和排隊(duì)的任務(wù)總數(shù)
runtime.NumGoroutine函數(shù)在被調(diào)用后,會(huì)返回系統(tǒng)中的處于特定狀態(tài)的Goroutine的數(shù)量。這里的特指是指Grunnable\Gruning\Gsyscall\Gwaition。處于這些狀態(tài)的Groutine即被看做是活躍的或者說正在被調(diào)度。
注意:垃圾回收所在Groutine的狀態(tài)也處于這個(gè)范圍內(nèi)的話,也會(huì)被納入該計(jì)數(shù)器。
runtime.GOOS
獲取目標(biāo)操作系統(tǒng)
func GOROOT() string
獲取當(dāng)前GOROOT

3、cgo

CGO是實(shí)現(xiàn)Go與C互操作的方式,包括Go調(diào)C和C調(diào)Go兩個(gè)過程。Go調(diào)用C需要在程序中引入的一個(gè)偽包,import “C”即為在Go中使用的偽包。C偽包會(huì)在編譯前被CGO工具捕捉到,并做一些代碼的改寫和樁文件的生成,不會(huì)被Go編譯器見到。
Go語言中調(diào)用C程序的方法如下:

//自定義函數(shù)調(diào)用
package main

/*
#include <stdio.h>
#include <stdlib.h>
void output(char *str) {
   printf("%s\n", str);
}
*/
import "C"
import "unsafe"

func main() {
   str := C.CString("hello cgo")
   C.output(str)
   C.free(unsafe.Pointer(str))
}

4、調(diào)度器

每一個(gè)Go程序都附帶一個(gè)runtime,runtime負(fù)責(zé)與底層操作系統(tǒng)交互,也都會(huì)有scheduler對(duì)goruntines進(jìn)行調(diào)度。

四、plugin

1、plugin簡(jiǎn)介

Golang是靜態(tài)編譯型語言,在編譯時(shí)就將所有引用的包全部加載打包到最終的可執(zhí)行程序中,因此不能在運(yùn)行時(shí)動(dòng)態(tài)加載其它共享庫。Go 1.8開始,Go語言Linux和MacOS版本通過plugin包提供插件化加載共享庫機(jī)制,能夠在運(yùn)行時(shí)動(dòng)態(tài)加載外部功能。

2、plugin常用方法

type Plugin struct {
   pluginpath string
   err        string        // set if plugin failed to load
   loaded     chan struct{} // closed when loaded
   syms       map[string]interface{}
}

func Open(path string) (*Plugin, error)
func (p *Plugin) Lookup(symName string) (Symbol, error)

type Symbol interface{}

Open: 根據(jù)參數(shù)path提供的插件路徑加載插件,并返回插件結(jié)構(gòu)的指針*Plugin。
Lookup:?*Plugin的惟一方法,通過名稱symName在插件中尋找對(duì)應(yīng)的變量或方法,以Symbol的形式返回。從插件中找到的任何元素都是以Symbol形式(即interface{})返回,需要通過斷言的形式對(duì)結(jié)果進(jìn)行判斷和轉(zhuǎn)換,得到需要的類型。

3、插件編譯方法

Go語言編譯器使用-buildmode=plugin標(biāo)記編譯生成一個(gè)插件(共享對(duì)象庫文件)。Go包中導(dǎo)出的函數(shù)和變量被公開為ELF符號(hào),可以使用plugin包在運(yùn)行時(shí)查找并綁定ELF符號(hào)。
go build -buildmode=plugin -o xxxplugin.so xxxplugin.go
如果要想更好的控制插件版本,實(shí)現(xiàn)熱更新插件,可以采用自動(dòng)注冊(cè)插件方式。當(dāng)新版本插件加載后,自動(dòng)注冊(cè)插件版本號(hào),插件平臺(tái)里優(yōu)先使用新版本插件的方法。

4、插件使用示例

插件編寫HelloPlugin.go:

package main

import (
   "fmt"
)

func init() {
   fmt.Println("Hello")
}

func Hello() {
   fmt.Println("world")
}

插件編譯:
go build -buildmode=plugin -o HelloPlugin.so HelloPlugin.go
插件調(diào)用main.go:

package main

import (
   "fmt"
   "plugin"
)

func main() {
   open, err := plugin.Open("./HelloPlugin.so")
   if err != nil {
      fmt.Println(err.Error())
   }
   symbol, err := open.Lookup("Hello")
   if err != nil {
      fmt.Println(err)
   }
   symbol.(func())()
}

編譯運(yùn)行:
go run main.go

5、插件化編程

插件管理器實(shí)現(xiàn):

package PluginManager

import "fmt"

// 插件容器
var Plugins map[string]Plugin

func init() {
   Plugins = make(map[string]Plugin)
}

type Plugin interface {
   Start()
}

// 啟動(dòng)這個(gè)容器中所有的插件
func Start() {
   for name, plugin := range Plugins {
      go plugin.Start()
      fmt.Printf("%s Plugin Start.\n", name)
   }
}

// 插件做完之后必須得插入到容器中
func Register(name string, plugin Plugin) {
   Plugins[name] = plugin
}

插件實(shí)現(xiàn):

package HelloPlugin

import (
   "GoExample/Plugin/PluginManager"
   "fmt"
)

type HelloPlugin struct {
}

// 導(dǎo)入包時(shí)注冊(cè)插件
func init() {
   plugin := HelloPlugin{}
   PluginManager.Register("HelloPlugin", plugin)
}
func (this HelloPlugin) Start() {
   fmt.Println("This is HelloPlugin.")
}

插件使用:

package main

import "GoExample/Plugin/PluginManager"
import _ "GoExample/Plugin/HelloPlugin"

func main() {
   PluginManager.Start()
}

// output:
// HelloPlugin Plugin Start.

五、signal

1、signal簡(jiǎn)介

os/signal包可以實(shí)現(xiàn)對(duì)信號(hào)的處理,Notify方法用來監(jiān)聽收到的信號(hào),Stop方法用來取消監(jiān)聽。
func Notify(c chan &lt; - os.Signal, sig ...os.Signal)
Notify函數(shù)會(huì)將進(jìn)程收到的系統(tǒng)Signal轉(zhuǎn)發(fā)給channel c,轉(zhuǎn)發(fā)哪些信號(hào)由可變參數(shù)決定,SIGKILL和SIGSTOP不能被攔截和處理。
參數(shù)c表示接收信號(hào)的channel,后續(xù)參數(shù)表示設(shè)置要監(jiān)聽的信號(hào),如果不設(shè)置表示監(jiān)聽所有的信號(hào)。
func Stop(c chan &lt; - os.Signal)
Stop方法取消監(jiān)聽通道上的所有信號(hào)。

2、signal示例

package main

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

func main() {
   signalChannel := make(chan os.Signal, 1)
   done := make(chan bool, 1)
   // 監(jiān)聽SIGINT、SIGTERM
   signal.Notify(signalChannel, syscall.SIGINT, syscall.SIGTERM)
   go func(ch chan os.Signal) {
      // 接收信號(hào)
      channel := <-ch
      fmt.Printf("Received a signal: %s\n", channel)
      done <- true
   }(signalChannel)
   // signal.Stop(signalChannel)
   for {
      fmt.Println("Waiting signal.")
      <-done
      fmt.Println("Exiting.")
   }
}
向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI