亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

 更新時(shí)間:2019年01月14日 09:32:48   作者:winlin  
這篇文章主要介紹了GOLANG使用Context管理關(guān)聯(lián)goroutine的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

一般一個(gè)業(yè)務(wù)很少不用到goroutine的,因?yàn)楹芏喾椒ㄊ切枰却?,例?code>http.Server.ListenAndServe這個(gè)就是等待的,除非關(guān)閉了Server或Listener,否則是不會(huì)返回的。除非是一個(gè)API服務(wù)器,否則肯定需要另外起goroutine發(fā)起其他的服務(wù),而且對(duì)于API服務(wù)器來(lái)說(shuō),在http.Handler的處理函數(shù)中一般也需要起goroutine,如何管理這些goroutine,在GOLANG1.7提供context.Context。

先看一個(gè)簡(jiǎn)單的,如果啟動(dòng)兩個(gè)goroutine,一個(gè)是HTTP,還有個(gè)信號(hào)處理的收到退出信號(hào)做清理:

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

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

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() // 取消請(qǐng)求,通知用到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())
}

這個(gè)方式可以在新開(kāi)goroutine時(shí)繼續(xù)使用,譬如新加一個(gè)goroutine,里面讀寫(xiě)了UDPConn:

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,可以這么寫(xiě):

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

如果需要提供一個(gè)API來(lái)讓服務(wù)器退出,可以這么寫(xiě):

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。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • go語(yǔ)言中if語(yǔ)句用法實(shí)例

    go語(yǔ)言中if語(yǔ)句用法實(shí)例

    這篇文章主要介紹了go語(yǔ)言中if語(yǔ)句用法,以實(shí)例形式分析了if語(yǔ)句的定義及使用技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2015-02-02
  • Golang import 導(dǎo)入包語(yǔ)法及一些特殊用法詳解

    Golang import 導(dǎo)入包語(yǔ)法及一些特殊用法詳解

    這篇文章主要介紹了Golang import 導(dǎo)入包語(yǔ)法及一些特殊用法,需要的朋友可以參考下
    2020-02-02
  • 通過(guò)源碼分析Golang?cron的實(shí)現(xiàn)原理

    通過(guò)源碼分析Golang?cron的實(shí)現(xiàn)原理

    golang實(shí)現(xiàn)定時(shí)任務(wù)很簡(jiǎn)單,只須要簡(jiǎn)單幾步代碼即可以完成,最近在做了幾個(gè)定時(shí)任務(wù),想研究一下它內(nèi)部是怎么實(shí)現(xiàn)的,所以將源碼過(guò)了一遍,記錄和分享在此。需要的朋友可以參考以下內(nèi)容,希望對(duì)大家有幫助
    2022-10-10
  • Golang變量直接初始化的方法詳解

    Golang變量直接初始化的方法詳解

    在 Go 語(yǔ)言中,我們常用的數(shù)據(jù)結(jié)構(gòu)有在Go語(yǔ)言中,你可以初始化不同的數(shù)據(jù)結(jié)構(gòu),例如數(shù)組、切片、結(jié)構(gòu)體、指針、map等,本文將給大家介紹一下Golang變量直接初始化的方法,需要的朋友可以參考下
    2023-08-08
  • Go語(yǔ)言Gin處理響應(yīng)方式詳解

    Go語(yǔ)言Gin處理響應(yīng)方式詳解

    gin框架封裝了常用的數(shù)據(jù)格式方法響應(yīng)于客戶端,下面這篇文章主要給大家介紹了關(guān)于Go語(yǔ)言Gin處理響應(yīng)方式的相關(guān)資料,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2023-01-01
  • Go語(yǔ)言fmt.Sprintf格式化輸出的語(yǔ)法與實(shí)例

    Go語(yǔ)言fmt.Sprintf格式化輸出的語(yǔ)法與實(shí)例

    Go 可以使用 fmt.Sprintf 來(lái)格式化字符串,下面這篇文章主要給大家介紹了關(guān)于Go語(yǔ)言fmt.Sprintf格式化輸出的語(yǔ)法與實(shí)例,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-07-07
  • Go語(yǔ)言為什么不支持三元運(yùn)算符原理解析

    Go語(yǔ)言為什么不支持三元運(yùn)算符原理解析

    這篇文章主要為大家介紹了Go語(yǔ)言為什么不支持三元運(yùn)算符原理解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • 淺析Go語(yǔ)言的數(shù)據(jù)類型及數(shù)組

    淺析Go語(yǔ)言的數(shù)據(jù)類型及數(shù)組

    Golang是一種靜態(tài)強(qiáng)類型、編譯型語(yǔ)言。Go?語(yǔ)言語(yǔ)法與?C?相近,但功能上有:內(nèi)存安全,GC(垃圾回收),結(jié)構(gòu)形態(tài)及?CSP-style?并發(fā)計(jì)算。本文主要和大家聊聊Go語(yǔ)言的數(shù)據(jù)類型及數(shù)組,希望對(duì)大家有所幫助
    2022-11-11
  • Go語(yǔ)言程序開(kāi)發(fā)gRPC服務(wù)

    Go語(yǔ)言程序開(kāi)發(fā)gRPC服務(wù)

    這篇文章主要為大家介紹了Go語(yǔ)言程序開(kāi)發(fā)gRPC服務(wù),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • Go使用Viper庫(kù)讀取YAML配置文件的示例代碼

    Go使用Viper庫(kù)讀取YAML配置文件的示例代碼

    Viper是適用于Go應(yīng)用程序的完整配置解決方案,它被設(shè)計(jì)用于在應(yīng)用程序中工作,并且可以處理所有類型的配置需求和格式,本文給大家介紹了Go使用Viper庫(kù)讀取YAML配置文件的方法,需要的朋友可以參考下
    2024-05-05

最新評(píng)論