Go 中完成商场独霸的筹划

序言
往常斥地中我们大年夜大年夜体率会碰着商场独霸的中完场景,比如一个批量耗时义务 、成商场独筹划群集请求等;一个出色的中完商场独霸可以有效的阻拦一些问题(比如 goroutine 泄漏、成本不释放等)。成商场独筹划
Timer
在 go 中完成商场独霸的中完编制特别很是复杂,起首第一种筹划是成商场独筹划 Time.After(d Duration) :
func main() { fmt.Println(time.Now()) x := <-time.After(3 * time.Second) fmt.Println(x)}output:
2021-10-27 23:06:04.304596 +0800 CST m=+0.000085653
2021-10-27 23:06:07.306311 +0800 CST m=+3.001711390

time.After() 会前去一个 Channel ,该 Channel 会在延时 d 段时分后写进数据。中完
有了这个特点便可以完成一些异步独霸商场的成商场独筹划场景 :
func main() { ch := make(chan struct{ }, 1) go func() { fmt.Println("do something...") time.Sleep(4*time.Second) ch<- struct{ }{ } }() select { case <-ch: fmt.Println("done") case <-time.After(3*time.Second): fmt.Println("timeout") }}这里假定有一个 goroutine 在跑一个耗时义务,独霸 select 有一个 channel 取掉落踪掉落踪数据便介入的中完特点,当 goroutine 没有在无穷时额定完成义务时,成商场独筹划主 goroutine 便会介入 ,中完也就抵达了商场的成商场独筹划方针。
output:
do something...
timeout
timer.After 消弭,中完同时 Channel 发出消息 ,成商场独筹划也可以封锁通道等赐顾帮衬编制。中完
寄看 Channel 最好是有大年夜小 ,阻拦梗阻 goroutine ,招致泄漏。
Context
第二种筹划是独霸 context,go 的 context 下场壮除夜;

独霸 context.WithTimeout() 编制会前去一个具有商场下场的凹凸文。
ch := make(chan string) timeout, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() go func() { time.Sleep(time.Second * 4) ch <- "done" }() select { case res := <-ch: fmt.Println(res) case <-timeout.Done(): fmt.Println("timout", timeout.Err()) }一样的用法,context 的 Done() 函数会前去一个 channel,该 channel 会在往后工作完成或是凹凸文消弭奏效。
timout context deadline exceeded
经由过程 timeout.Err() 也能晓得往后 context 封锁的启事。
goroutine 传递 context
独霸 context 另有一个益处是 ,可以独霸其天然在多个 goroutine 中传递的特点 ,让全数传递了该 context 的 goroutine 同时领遭到消弭赐顾帮衬 ,这点在多 go 中独霸特别很是普及。
func main() { total := 12 var num int32 log.Println("begin") ctx, cancelFunc := context.WithTimeout(context.Background(), 3*time.Second) for i := 0; i < total; i++ { go func() { //time.Sleep(3 * time.Second) atomic.AddInt32(&num, 1) if atomic.LoadInt32(&num) == 10 { cancelFunc() } }() } for i := 0; i < 5; i++ { go func() { select { case <-ctx.Done(): log.Println("ctx1 done", ctx.Err()) } for i := 0; i < 2; i++ { go func() { select { case <-ctx.Done(): log.Println("ctx2 done", ctx.Err()) } }() } }() } time.Sleep(time.Second*5) log.Println("end", ctx.Err()) fmt.Printf("奉行终了 %v", num)}在以上例子中,非论 goroutine 嵌套了若干很多若干良多若干很多若干良多若干很多若干层 ,都是可以在 context 消弭时掉落踪掉落踪消息(当然前提是 context 得传递走)
某些出格气候需求延迟消弭 context 时 ,也可以手动调用 cancelFunc() 函数 。
Gin 中的案例
Gin 供给的 Shutdown(ctx) 函数也充分独霸了 context。
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() if err := srv.Shutdown(ctx); err != nil { log.Fatal("Server Shutdown:", err) } log.Println("Server exiting")
比如以上代码等于商场等待 10s 举办 Gin 的成本释放,完成的事理也和上文的例子不异。
总结
因为写 go 的时分不长 ,所以本身写了一个练手的项目:一个接口压力测试对象 。


个中一个很罕有的需求就是压测 N 秒撤离猬缩猬缩出,这里正好就独霸到了相干常识点,一样是初学 go 的小火伴可以参考 。
https://github.com/crossoverJie/ptg/blob/d0781fcb5551281cf6d90a86b70130149e1525a6/duration.go
到此这篇关于Go言语 里的商场独霸的文章就引见到这了,更多相干Go 商场独霸内容请搜刮完竣下载之前的文章或延续不雅不雅不雅不雅鉴赏上面的相干文章希看大年夜师往后多多支撑完竣下载!
