一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

腳本之家,腳本語言編程技術(shù)及教程分享平臺!
分類導(dǎo)航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務(wù)器之家 - 腳本之家 - Golang - GOLANG使用Context管理關(guān)聯(lián)goroutine的方法

GOLANG使用Context管理關(guān)聯(lián)goroutine的方法

2020-05-22 09:39winlin Golang

這篇文章主要介紹了GOLANG使用Context管理關(guān)聯(lián)goroutine的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

一般一個業(yè)務(wù)很少不用到goroutine的,因為很多方法是需要等待的,例如http.Server.ListenAndServe這個就是等待的,除非關(guān)閉了Server或Listener,否則是不會返回的。除非是一個API服務(wù)器,否則肯定需要另外起goroutine發(fā)起其他的服務(wù),而且對于API服務(wù)器來說,在http.Handler的處理函數(shù)中一般也需要起goroutine,如何管理這些goroutine,在GOLANG1.7提供context.Context。

先看一個簡單的,如果啟動兩個goroutine,一個是HTTP,還有個信號處理的收到退出信號做清理:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
wg := sync.WaitGroup{}
defer wg.Wait()
 
wg.Add(1)
go func() {
  defer wg.Done()
 
  ss := make(os.Signal, 0)
  signal.Notify(ss, syscall.SIGINT, syscall.SIGTERM)
  for s := ss {
    fmt.Println("Got signal", s)
    break
  }
}()
 
wg.Add(1)
go func() {
  defer wg.Done()
 
  svr := &http.Server{ Addr:":8080", Handler:nil, }
  fmt.Println(svr.ListenAndServe())
}

很清楚,起了兩個goroutine,然后用WaitGroup等待它們退出。如果它們之間沒有交互,不互相影響,那真的是蠻簡單的,可惜這樣是不行的,因為信號的goroutine收到退出信號后,應(yīng)該通知server退出。暴力一點的是直接調(diào)用svr.Close(),但是如果有些請求還需要取消怎么辦呢?最好用Context了:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
wg := sync.WaitGroup{}
defer wg.Wait()
 
ctx,cancel := context.WithCancel(context.Background())
 
wg.Add(1)
go func() {
  defer wg.Done()
 
  ss := make(chan os.Signal, 0)
  signal.Notify(ss, syscall.SIGINT, syscall.SIGTERM)
  select {
  case <- ctx.Done():
    return
  case s := <- ss:
    fmt.Println("Got signal", s)
    cancel() // 取消請求,通知用到ctx的所有g(shù)oroutine
    return
  }
}()
 
wg.Add(1)
go func() {
  defer wg.Done()
  defer cancel()
 
  svr := &http.Server{ Addr:":8080", Handler:nil, }
 
  go func(){
    select {
    case <- ctx.Done():
      svr.Close()
    }
  }
 
  fmt.Println(svr.ListenAndServe())
}

這個方式可以在新開goroutine時繼續(xù)使用,譬如新加一個goroutine,里面讀寫了UDPConn:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
wg.Add(1)
go func() {
  defer wg.Done()
  defer cancel()
 
  var conn *net.UDPConn
  if conn,err = net.Dial("udp", "127.0.0.1:1935"); err != nil {
    fmt.Println("Dial UDP server failed, err is", err)
    return
  }
 
  fmt.Println(UDPRead(ctx, conn))
}()
 
UDPRead = func(ctx context.Context, conn *net.UDPConn) (err error) {
  wg := sync.WaitGroup{}
  defer wg.Wait()
 
  ctx, cancel := context.WithCancel(ctx)
 
  wg.Add(1)
  go func() {
    defer wg.Done()
    defer cancel()
 
    for {
      b := make([]byte, core.MTUSize)
      size, _, err := conn.ReadFromUDP(b)
      // 處理UDP包 b[:size]
    }
  }()
 
  select {
  case <-ctx.Done():
    conn.Close()
  }
  return
}

如果只是用到HTTP Server,可以這么寫:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
func run(ctx contex.Context) {
  server := &http.Server{Addr: addr, Handler: nil}
  go func() {
    select {
    case <-ctx.Done():
      server.Close()
    }
  }()
 
  http.HandleFunc("/api", func(w http.ResponseWriter, r *http.Request) {
  })
 
  fmt.Println(server.ListenAndServe())
}

如果需要提供一個API來讓服務(wù)器退出,可以這么寫:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
func run(ctx contex.Context) {
  server := &http.Server{Addr: addr, Handler: nil}
 
  ctx, cancel := context.WithCancel(ctx)
  http.HandleFunc("/quit", func(w http.ResponseWriter, r *http.Request) {
    cancel() // 使用局部的ctx和cancel
  })
 
  go func() {
    select {
    case <-ctx.Done():
      server.Close()
    }
  }()
 
  fmt.Println(server.ListenAndServe())
}

使用局部的ctx和cancel,可以避免cancel傳入的ctx,只是影響當(dāng)前的ctx。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。

原文鏈接:https://gocn.vip/article/333

延伸 · 閱讀

精彩推薦
  • Golanggolang如何使用struct的tag屬性的詳細(xì)介紹

    golang如何使用struct的tag屬性的詳細(xì)介紹

    這篇文章主要介紹了golang如何使用struct的tag屬性的詳細(xì)介紹,從例子說起,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看...

    Go語言中文網(wǎng)11352020-05-21
  • GolangGolang中Bit數(shù)組的實現(xiàn)方式

    Golang中Bit數(shù)組的實現(xiàn)方式

    這篇文章主要介紹了Golang中Bit數(shù)組的實現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧...

    天易獨尊11682021-06-09
  • Golanggolang的httpserver優(yōu)雅重啟方法詳解

    golang的httpserver優(yōu)雅重啟方法詳解

    這篇文章主要給大家介紹了關(guān)于golang的httpserver優(yōu)雅重啟的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,...

    helight2992020-05-14
  • Golanggo日志系統(tǒng)logrus顯示文件和行號的操作

    go日志系統(tǒng)logrus顯示文件和行號的操作

    這篇文章主要介紹了go日志系統(tǒng)logrus顯示文件和行號的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧...

    SmallQinYan12302021-02-02
  • Golanggolang 通過ssh代理連接mysql的操作

    golang 通過ssh代理連接mysql的操作

    這篇文章主要介紹了golang 通過ssh代理連接mysql的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧...

    a165861639710342021-03-08
  • Golanggo語言制作端口掃描器

    go語言制作端口掃描器

    本文給大家分享的是使用go語言編寫的TCP端口掃描器,可以選擇IP范圍,掃描的端口,以及多線程,有需要的小伙伴可以參考下。 ...

    腳本之家3642020-04-25
  • GolangGolang通脈之?dāng)?shù)據(jù)類型詳情

    Golang通脈之?dāng)?shù)據(jù)類型詳情

    這篇文章主要介紹了Golang通脈之?dāng)?shù)據(jù)類型,在編程語言中標(biāo)識符就是定義的具有某種意義的詞,比如變量名、常量名、函數(shù)名等等,Go語言中標(biāo)識符允許由...

    4272021-11-24
  • Golanggolang json.Marshal 特殊html字符被轉(zhuǎn)義的解決方法

    golang json.Marshal 特殊html字符被轉(zhuǎn)義的解決方法

    今天小編就為大家分享一篇golang json.Marshal 特殊html字符被轉(zhuǎn)義的解決方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧 ...

    李浩的life12792020-05-27
主站蜘蛛池模板: 国产欧美日韩精品一区二区三区 | 美女扒开胸罩露出奶了无遮挡免费 | 欧美一区二区三区高清不卡tv | 日本丰满www色 | 俄罗斯美女毛茸茸bbwbbw | 久久久久久久伊人电影 | 国产一级特黄在线播放 | 久久综合网久久综合 | 国产精品1页 | 久久中文电影 | avtt在线播放 | 国产高清不卡视频在线播放 | 教室眠催白丝美女校花 | 久久永久影院免费 | 60岁妇女毛片免费观看 | 欧美特欧美特级一片 | 久青草国产观看在线视频 | 好涨好大我快受不了了视频网 | 色综合天天娱乐综合网 | 精品国产免费久久久久久 | 亚洲精品资源 | 天天草b| 亚洲国产情侣偷自在线二页 | 九九精品影院 | 门卫老张和女警花小说 | 日本护士厕所xxx | 维修工的调教 | 九九99热久久999精品 | 欧美一级片观看 | 欧洲久久 | 亚洲香蕉网久久综合影院3p | 日韩理论片 | 精品99在线观看 | 亚洲人成网站在线观看90影院 | 禁忌4中文 | 国产精品日韩在线观看 | 齐天大性之七仙女欲春迅雷链接 | 亚洲va在线va天堂成人 | 欧美黑人性 | 日本精工厂网址 | 四虎成人www国产精品 |