Golang并发情况下变量的复制
最近采用golang编程语言开发,深刻体会到了golang语言并行的便利性,但是也带来了一些小问题,
问题不大,我们来解决。先来看一下什么是并发。
什么是并行? 什么是并发?
- 并行的关键是同时可以做很多事情,常见的有多机并行,多核并行;并发是同时管理很多事情,在规定时间内这些事情都能得到执行。
- 并发重在避免阻塞,使程序不会因为阻塞而停止执行;并行则是依赖硬件和操作系统的资源。
- 并发在于结构,并行在于执行。应用程序具备好的并发结构,操作系统才能更好地利用硬件并行执行,合理地进行调度,提升CPU利用率。
golang中,我们都是说的并行,努力挖掘机器的潜能,充分利用机器的多核特性,使代码执行效率最高。
golang中并行利用的是语言的内置函数 go ,来起一个协程。这个协程就叫 goroutine
什么是goroutine?
goroutine是建立在线程之上的轻量级的抽象。在Go语言中,当一个函数被创建为goroutine时,Go会将其视为一个独立的工作单元,并且能够以非常低的代价实现并行执行多个goroutine。
说一说,今天遇到的问题,
我在一个循环中,起了一组goroutinue ,每个协程去执行一个函数,在这个函数中,
func (s *ServiceImpl) getData(
ctx context.Context,
aa int64,
where []string,
) (data Data,err error) {
queryWhere := where
发现每次请求都会有问题,
每次会查询十条数据,但是每次的组装SQL都有问题,有问题的SQL也是随机的。
于是我在代码中打印日志看一下,
发现日志输出,结果居然也正常了
这就奇怪了,添加一句打日志的代码就正确了,
去除 日志代码,问题又100%复现。
最终各种查找问题,突然发现,queryWhere是一个slice ,
还是基础知识问题呀,golang中slice在底层用的是数组,而且是复用的数组,
把代码改成
func (s *ServiceImpl) getData(
ctx context.Context,
aa int64,
where []string,
) (data Data,err error) {
queryWhere := make([]string, len(where))
copy(queryWhere, where)
不添加日志语句,问题也解决了。
还是得多打基础呀