Go错误集锦 | append操作造成数据竞争
2023-06-13 09:16:47 时间
在Go中,使用append给切片中添加元素是常见的操作。下面我们看一个使用append引起的数据竞争的例子。
在下面的示例中,我们创建一个长度为1的切片,然后通过两个协程使用append往该切片中添加元素,如下:
s := make([]int, 1)
go func() {
s1 := append(s, 1)
fmt.Println(s1)
}()
go func() {
s2 := append(s, 2)
fmt.Println(s2)
}()
在该示例中,会产生数据竞争吗?答案是不会。我们看下为什么。
首先,我们回顾一下slice的基础知识。slice结构的底层是一个数组,另外还有两个属性:长度length和容量cap。长度是指的切片中当前有多少个元素。容量是指底层的数组能容纳的总的元素个数。当使用append操作时,其行为依赖于该slice是否满了,即length是否和cap相等。如果slice已经满了,那么append的操作将会重新分配一个更大空间的新数组,然后将原数组中的元素拷贝过来,再将新元素加在新数组中。如果slice没满,那么append的操作是将新元素直接加到已存在的数组中。
在该示例中,我们创建的切片s的长度和容量都是1,即该切片是满的状态。所以在协程中使用append操作,则各自都会创建一个新的数组,并将新元素添加到自己的新数组中,两个数组空间互不影响。所以不存在是数据竞争的问题。
那如果我们将初始化切片的语句变更成如下这样:
s := make([]int, 0, 1)
同样还是在两个协程中使用append操作给s中添加新的元素,那这样就会导致数据竞争。因为在创建切片s的时候其长度为0,但容量是1,说明该切片是未满的状态,还有空间可以存放数据,所以在协程中使用append进行操作时,实际上是在争抢s[0]的位置。
好了,以上就是今天我们要分享的知识点,希望大家在今后的研发中避免踩同样的坑。
欢迎关注「Go学堂」,让知识活起来
相关文章
- go 并发模式
- [Go疑难杂症]为什么nil不等于nil
- Go 数据类型篇(六):切片使用入门和数据共享问题处理
- 2022-12-31:以下go语言代码输出什么?A:1 1;B:-1 1;C:-1 -1;D:编译错误。 package main import “fmt“ f
- Go学设计模式-程序流程要动态切换?用这个模式写更丝滑
- Go常见错误集锦之append操作slice时的副作用
- Go常见错误集锦之copy函数复制slice时为什么不成功
- Go常见错误集锦之函数式选项模式
- Go 指针、uintptr、unsafe.Pointer之间如何转换
- go的数据类型-其他数据类型-function(一)
- Go-标准库-log(一)
- Go-标准库-log(二)
- Go-标准库-strconv(二)
- Go-包管理-go clean
- 流行的Go语言web框架简介详解大数据
- Go-连接Redis-学习go-redis包详解编程语言
- Go语言使用通道响应计时器的事件
- 精通Go语言开发Redis应用(go语言redis开发)
- 深度探索Go语言与Redis结合(go-redis)
- 毁誉交加的14个月后,Amazon Go 终于对外开放,商业意义有多大?
- 如何在Linux上安装Go语言?——简单易懂的指南(linux安装go语言)
- Go语言链接Oracle数据库的实践记录(go 链接oracle)
- 提升Go读取Oracle的速度(go读取oracle速度)
- Go语言搭建Oracle数据库快速连接方法(go语言连接oracle)