GOLANG使用Context管理關(guān)聯(lián)goroutine的方法
一般一個(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í)有所幫助,也希望大家多多支持腳本之家。
- 深入Golang之context的用法詳解
- GOLANG使用Context實(shí)現(xiàn)傳值、超時(shí)和取消的方法
- GoLang之使用Context控制請(qǐng)求超時(shí)的實(shí)現(xiàn)
- 使用Golang的Context管理上下文的方法
- golang中context的作用詳解
- golang通過(guò)context控制并發(fā)的應(yīng)用場(chǎng)景實(shí)現(xiàn)
- 詳解Golang中Context的三個(gè)常見(jiàn)應(yīng)用場(chǎng)景
- 提升Golang應(yīng)用性能:深入理解Context的應(yīng)用
相關(guān)文章
Golang import 導(dǎo)入包語(yǔ)法及一些特殊用法詳解
這篇文章主要介紹了Golang import 導(dǎo)入包語(yǔ)法及一些特殊用法,需要的朋友可以參考下2020-02-02通過(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-10Go語(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ǔ)言的數(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-11Go語(yǔ)言程序開(kāi)發(fā)gRPC服務(wù)
這篇文章主要為大家介紹了Go語(yǔ)言程序開(kāi)發(fā)gRPC服務(wù),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06