go 协程使用准则

前言

​ go 异步编程的便利是其能够流行的一部分原因,仅需一个 go 关键字就可以开启一个异步流程。得益于 goroutine 轻量级的设计和使用的便利性,导致 goroutine 被不正确的使用或滥用。线上由于 goroutine 使用不善导致的 panic、内存泄漏等问题屡见不鲜。

为什么做 go 协程管理
  1. 忘记加 defer recover 导致的 panic,go 的主协程里面加了 recover ,子协程依然需要加 recover,具体原因参考文章:go 设计与实现 - panic
  2. 未正确回收协程导致的内存泄漏
协程使用准则
  1. 使用 recover 避免 panic 导致的系统崩溃,又时候我们总是自信程序肯定没问题,但墨菲定律总是在生效,可能发生的错误一定会发生。
  2. 做好超时控制
  3. 使用 sync.WaitGroup 做好 go 生命周期管理
协程泄露案例
不正确使用阻塞 Channel

​ 代码演示地址:执行

// basic is a program used to define a goroutine leak.
package main

import (
	"fmt"
	"runtime"
	"time"
)

func main() {

	// Capture starting number of goroutines.
	startingGs := runtime.NumGoroutine()

	leak()

	// Hold the program from terminating for 1 second to see
	// if any goroutines created by leak terminate.
	time.Sleep(time.Second)

	// Capture ending number of goroutines.
	endingGs := runtime.NumGoroutine()

	// Report the results.
	fmt.Println("========================================")
	fmt.Println("Number of goroutines before:", startingGs)
	fmt.Println("Number of goroutines after :", endingGs)
	fmt.Println("Number of goroutines leaked:", endingGs-startingGs)
}

// leak is a buggy function. It launches a goroutine that
// blocks receiving from a channel. Nothing will ever be
// sent on that channel and the channel is never closed so
// that goroutine will be blocked forever.
func leak() {
	ch := make(chan int)

	go func() {
		val := <-ch
		fmt.Println("We received a value:", val)
	}()
}

执行结果

在这里插入图片描述

从执行结果可以看到出现了一个协程泄漏,原因是由于 没地方消费这个 channel 从而导致协程泄漏

超时导致的协程泄漏
package main

func main() {
 ch := make(chan bool)

	ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*100)
	defer cancel()

	go leak(ctx, ch)

	select {
	case <-ctx.Done():
		fmt.Println("done, err: ", ctx.Err())
	case <-ch:
		return
	}
}

func leak(ctx context.Context, ch chan bool) {
	time.Sleep(time.Second)
	ch <- true
}

这个程序由于 leak 超时,ch 将由于没人消费永远阻塞

总结

​ 这是一篇关于 goroutine 使用不当会引起的问题以及goroutine使用注意事项,本文旨在提高开发者的协程使用意识,使用协程的时候时刻记住 “永远不要开启你不知道什么时候结束的 goroutine

Github:https://wang1309.github.io/

Reference
  1. https://www.ardanlabs.com/blog/2018/11/goroutine-leaks-the-forgotten-sender.html
  2. https://www.ardanlabs.com/blog/2019/04/concurrency-trap-2-incomplete-work.html
  3. https://www.ardanlabs.com/blog/2014/01/concurrency-goroutines-and-gomaxprocs.html
  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值