二十六、实战化goroutine

目录

1、未使用goroutine时

2、使用goroutine时

3、使用WaitGroup等待并发结束

4、利用defer方法体再优化


为什么要使用并发,因为并发能大大提高效率,以下案例可以通过执行时间直观的感受到差别

例如以下方法

1、未使用goroutine时

var students = map[int64]student{
	1: {
		id:   1,
		name: "zs",
	},
	2: {
		id:   2,
		name: "ls",
	},
}

type student struct {
	id   int
	name string
}

func getStudent(id int64) student {
	time.Sleep(1 * time.Second)
	return students[id]
}

func one() {
	start := time.Now()
	ids := []int64{1, 2}
	for _, id := range ids {
		fmt.Println(getStudent(id))

	}
	end := time.Since(start)
	fmt.Println(end)
}

func main() {
	one()
}

通过时间上来看肯定是大于2秒的,timeSleep模拟处理业务需要花费的时间

2、使用goroutine时

新增函数two

func two() {
	start := time.Now()
	ids := []int64{1, 2}
	for _, id := range ids {
		go func() {
			s := getStudent(id)
			fmt.Println(s)
		}()
	}
	end := time.Since(start)
	fmt.Println(end)
	time.Sleep(1 * time.Minute)

}

结果:

19.5µs

从结果上来看不用再顺序执行代码了,大大增加了程序的性能

建议标准写法,将id值作为参数传入并发方法体中

3、使用WaitGroup等待并发结束

上述代码中为了查看到最终结果,使用的是time.Sleep(1 * time.Minute )但是在正常的程序中肯定不会这么去使用的,所以我们要使用waitGroup来进行等待并发结束 

var (
	eg sync.WaitGroup
)

func two() {
	//表示每add一次记录一个并发(协程)在执行,完成一个-1
	start := time.Now()
	ids := []int64{1, 2}
	for _, id := range ids {
		eg.Add(1)
		go func(id int64) {
			s := getStudent(id)
			fmt.Println(s)
			//表示这个并发(协程)完成了
			eg.Done()
		}(id)
	}
	//当记录的并发(协程)数为0,则全部并发结束了
	eg.Wait()
	end := time.Since(start)
	fmt.Println(end)
}

结果:

{2 ls}
{1 zs}
1.001023916s
解释:

在外面我创建了一个sync.WaitGroup ,使用eg.add相当于记数每执行一次并发记录一次,执行完成一个减去一次,eg.done函数记录并发次数-1,最后调用eg.Wait()发现计数为0后则表示这几个并发完成了

4、利用defer方法体再优化

在实际开发中,当我们对函数的返回添加error后,如果这里我不是设错误为nil,如果我创建一个errors.new("查询错误"),同时如果我们继续把eg.done放到最后那么久没有办法去执行到eg.done,所以我们使用defer方法体去进行再次的优化

func getStudent(id int64) (student, error) {
	time.Sleep(1 * time.Second)
	return students[id], nil
}

func two() {
	//表示每add一次记录一个并发(协程)在执行,
	start := time.Now()
	ids := []int64{1, 2}
	for _, id := range ids {
		eg.Add(1)
		go func(id int64) {
			defer func() {
				eg.Done()
			}()
			s, err := getStudent(id)
			if err != nil {
				return
			}
			fmt.Println(s)
		}(id)
	}
	//当记录的并发(协程)数为0,则全部并发结束了
	eg.Wait()
	end := time.Since(start)
	fmt.Println(end)
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值