介绍
这篇文章给大家介绍怎么在GOLANG中利用上下文管理关联goroutine,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。
wg :=, sync.WaitGroup {} defer wg.Wait () wg.Add (1) go func (), { defer 才能;wg.Done () ss 才能:=,(os.Signal, 0) signal.Notify才能(ss, syscall.SIGINT,, syscall.SIGTERM) for 才能;s :=, ss { ,,,fmt.Println (“Got  signal",,) ,才能打破 ,,} } () wg.Add (1) go func (), { defer 才能;wg.Done () svr 才能;:=,,http.Server {, Addr:“: 8080,,,处理程序:nil,,} fmt.Println才能(svr.ListenAndServe ()) }
很清楚,起了两个goroutine,然后用WaitGroup等待它们退出。如果它们之间没有交互,不互相影响,那真的是蛮简单的,可惜这样是不行的,因为信号的goroutine收到退出信号后,应该通知服务器退出暴。力一点的是直接调用<代码> svr.Close()> 代码,但是如果有些请求还需要取消怎么办呢?最好了用上下文:
wg :=, sync.WaitGroup {} defer wg.Wait () ctx, cancel :=, context.WithCancel (context.Background ()) wg.Add (1) go func (), { defer 才能;wg.Done () ss 才能:=,(chan os.Signal, 0) signal.Notify才能(ss, syscall.SIGINT,, syscall.SIGTERM) select {才能 case 才能;& lt;作用;ctx.Done (): ,才能返回 case 才能;s :=, & lt;作用;ss: ,,,fmt.Println (“Got  signal",,) ,,,取消(),//,取消请求,通知用到ctx的所有goroutine ,才能返回 ,,} } () wg.Add (1) go func (), { defer 才能;wg.Done () defer 才能;取消() svr 才能;:=,,http.Server {, Addr:“: 8080,,,处理程序:nil,,} go 才能;func () { ,,,select { ,,,case & lt;作用;ctx.Done (): ,,,,,svr.Close () ,,,} ,,} fmt.Println才能(svr.ListenAndServe ()) }
这个方式可以在新开goroutine时继续使用,譬如新加一个goroutine,里面读写了UDPConn:
wg.Add (1) go func (), { defer 才能;wg.Done () defer 才能;取消() var 才能;conn * net.UDPConn err  if 才能,康涅狄格州,=,net.Dial (“udp",,“127.0.0.1:1935");, err !=, nil { ,,,fmt.Println (“Dial  UDP server 失败了,,err 女儿家,,,呃) ,才能返回 ,,} fmt.Println才能(UDPRead (ctx,康涅狄格州)) } () 时间=UDPRead func (ctx context.Context, conn * net.UDPConn), (err 错误),{ wg 才能;:=,sync.WaitGroup {} defer 才能;wg.Wait () ,,ctx, cancel :=, context.WithCancel (ctx) wg.Add才能(1) go 才能;func (), { ,,,defer wg.Done () ,,,defer 取消() ,,,for { ,,,,,b :=,([]字节,,core.MTUSize) ,,,,,,,,err _:=, conn.ReadFromUDP (b) ,,,,,//,处理UDP包,b(尺寸): ,,,} }()才能 select {才能 case 才能;& lt; -ctx.Done (): ,,,conn.Close () ,,} ,返回 }
如果只是用到HTTP服务器,可以这么写:
func 运行(ctx contex.Context), { server 才能;:=,,http.Server {Addr: Addr,,处理程序:,nil} go 才能;func (), { ,,,select { ,,,case & lt; -ctx.Done (): ,,,,,server.Close () ,,,} }()才能 http.HandleFunc才能(“/api",, func (w http.ResponseWriter, r * http.Request), { })才能 fmt.Println才能(server.ListenAndServe ()) }
如果需要提供一个API来让服务器退出,可以这么写:
func 运行(ctx contex.Context), { server 才能;:=,,http.Server {Addr: Addr,,处理程序:,nil} ,,ctx, cancel :=, context.WithCancel (ctx) http.HandleFunc才能(“/quit",, func (w http.ResponseWriter, r * http.Request), { ,,,取消(),//,使用局部的ctx和取消 })才能 go 才能;func (), { ,,,select { ,,,case & lt; -ctx.Done (): ,,,,,server.Close () ,,,} }()才能 fmt.Println才能(server.ListenAndServe ()) }
使用局部的ctx和取消,可以避免取消传入的ctx,只是影响当前的ctx。