golang中切片copy复制和等号复制的区别介绍


Posted in Golang onApril 27, 2021

结论:

copy复制会比等号复制慢。但是copy复制为值复制,改变原切片的值不会影响新切片。而等号复制为指针复制,改变原切片或新切片都会对另一个产生影响。

测试复制速度:

func TestArr1(t *testing.T) {
 var a []int
 for i := 0; i < 100000000; i++ {
  a = append(a, i)
 }
 start := time.Now().UnixNano()
 var b = make([]int, 1000000)
 copy(b, a)
 end := time.Now().UnixNano()
 fmt.Println(end - start)
}

结果为 5001100

func TestArr2(t *testing.T) {
 var a []int
 for i := 0; i < 100000000; i++ {
  a = append(a, i)
 }
 start := time.Now().UnixNano()
 var b = a[0:1000000]
 end := time.Now().UnixNano()
 fmt.Println(end - start)
 _ = b
}

结果为0

结论:

等号复制要比copy赋值速度快

测试更改原切片是否影响新切片:

func TestArr1(t *testing.T) {
 var a []int
 for i := 0; i < 100; i++ {
  a = append(a, i)
 }
 var b = make([]int, 10)
 copy(b, a)
 a[0] = 999
 fmt.Println(b[0])
}

结果0

func TestArr2(t *testing.T) {
 var a []int
 for i := 0; i < 100; i++ {
  a = append(a, i)
 }
 var b = a[0:10]
 a[0] = 999
 fmt.Println(b[0])
}

结果 999

结论:

copy为值复制,更改原切片不会影响新切片,而等号复制相反

补充:go语言,切片研究,容量,长度,复制,追加

今天学习了数组和切片,感觉数组不够灵活,一旦创建,无法添加成员。但是切片就灵活多了,感觉切片存在两种形态,第一种是映射数组来的,那么数组数据变化后,切片数据也变化,h j为映射切片 ,第二 种是独立切片,切片独立创建,并不依赖于任何数组, x y z均为独立切片,z拷贝自y,当y数据改变时,z不受影响。

另外发现个有趣的事,就是切片容量 len,x刚创建时,容量是10,长度是10,增加一个成员后,容量变成20,长度变成11,说明append函数,在增加成员的时候,会大幅度增加容量,但是再看y,它采用循环增加成员的方式创建,创建完成后,长度是10,容量是16。

代码:

var ar = [10]byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}
    var h, j []byte
    h = ar[2:5]
    j = ar[0:8]
    ar[2] = 'q'
    fmt.Println(string(h))
    fmt.Println(string(j))
    fmt.Printf("j容量%s\n", cap(j))
    fmt.Printf("j长度%s\n", len(j))
    x := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
    fmt.Println(x)
    fmt.Printf("x容量%s\n", cap(x))
    fmt.Printf("x长度%s\n", len(x))
    x = append(x, 11)
    fmt.Println(x)
    fmt.Printf("x容量%s\n", cap(x))
    fmt.Printf("x长度%s\n", len(x))
    var y []int
    for u := 0; u < 10; u++ {
        //y = append(y, fmt.Sprintf("%v", u))
        y = append(y, u)
    }
    fmt.Println(y)
    fmt.Printf("y容量%s\n", cap(y))
    fmt.Printf("y长度%s\n", len(y))
    y = append(y, 5)
    fmt.Println(y)
    var z = make([]int, len(y))
    copy(z, y)
    fmt.Println(z)
    y[0] = 9
    fmt.Println(y)
    fmt.Println(z)

结果

qde

abqdefgh

j容量%!s(int=10)

j长度%!s(int=8)

[0 1 2 3 4 5 6 7 8 9]

x容量%!s(int=10)

x长度%!s(int=10)

[0 1 2 3 4 5 6 7 8 9 11]

x容量%!s(int=20)

x长度%!s(int=11)

[0 1 2 3 4 5 6 7 8 9]

y容量%!s(int=16)

y长度%!s(int=10)

[0 1 2 3 4 5 6 7 8 9 5]

[0 1 2 3 4 5 6 7 8 9 5]

[9 1 2 3 4 5 6 7 8 9 5]

[0 1 2 3 4 5 6 7 8 9 5]

后来我再给y加入个成员,他的容量还是16,为了弄清容量和长度的关系

我写个循环看看

for u := 0; u < 20; u++ {
        //y = append(y, fmt.Sprintf("%v", u))
        y = append(y, u)
        fmt.Printf("y长度%s\n", len(y))
        fmt.Printf("y容量%s\n", cap(y))
    }

结果是

y长度%!s(int=1)

y容量%!s(int=2)

y长度%!s(int=2)

y容量%!s(int=2)

y长度%!s(int=3)

y容量%!s(int=4)

y长度%!s(int=4)

y容量%!s(int=4)

y长度%!s(int=5)

y容量%!s(int=8)

y长度%!s(int=6)

y容量%!s(int=8)

y长度%!s(int=7)

y容量%!s(int=8)

y长度%!s(int=8)

y容量%!s(int=8)

y长度%!s(int=9)

y容量%!s(int=16)

y长度%!s(int=10)

y容量%!s(int=16)

y长度%!s(int=11)

y容量%!s(int=16)

y长度%!s(int=12)

y容量%!s(int=16)

y长度%!s(int=13)

y容量%!s(int=16)

y长度%!s(int=14)

y容量%!s(int=16)

y长度%!s(int=15)

y容量%!s(int=16)

y长度%!s(int=16)

y容量%!s(int=16)

y长度%!s(int=17)

y容量%!s(int=32)

y长度%!s(int=18)

y容量%!s(int=32)

y长度%!s(int=19)

y容量%!s(int=32)

y长度%!s(int=20)

y容量%!s(int=32)

呵呵 ,这下明白了,添加成员时,容量是2的指数递增的,2,4,8,16,32。

而且是在长度要超过容量时,才增加容量。

我想在以后的开发中,切片我一定会比数组用的多,因为在原来的项目里,几乎所有数组都是无法提前知道它的长度的,都是会随时增加成员的。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持三水点靠木。如有错误或未考虑完全的地方,望不吝赐教。

Golang 相关文章推荐
golang判断key是否在map中的代码
Apr 24 Golang
golang 如何用反射reflect操作结构体
Apr 28 Golang
golang日志包logger的用法详解
May 05 Golang
go语言中GOPATH GOROOT的作用和设置方式
May 05 Golang
goland 设置project gopath的操作
May 06 Golang
使用golang编写一个并发工作队列
May 08 Golang
go语言使用Casbin实现角色的权限控制
Jun 26 Golang
Golang的继承模拟实例
Jun 30 Golang
Go语言基础知识点介绍
Jul 04 Golang
go开发alertmanger实现钉钉报警
Jul 16 Golang
GoFrame基于性能测试得知grpool使用场景
Jun 21 Golang
Go 内联优化让程序员爱不释手
Jun 21 Golang
go语言中切片与内存复制 memcpy 的实现操作
Apr 27 #Golang
Go语言中的UTF-8实现
Apr 26 #Golang
golang中实现给gif、png、jpeg图片添加文字水印
Apr 26 #Golang
Go语言带缓冲的通道实现
Apr 26 #Golang
go语言求任意类型切片的长度操作
Apr 26 #Golang
golang如何去除多余空白字符(含制表符)
Apr 25 #Golang
用golang如何替换某个文件中的字符串
Apr 25 #Golang
You might like
php minixml详解
2008/07/19 PHP
php多个字符串替换成同一个的解决方法
2013/06/18 PHP
php上传图片到指定位置路径保存到数据库的具体实现
2013/12/30 PHP
浅谈PHP各环境下的伪静态配置
2019/03/13 PHP
Laravel 模型使用软删除-左连接查询-表起别名示例
2019/10/24 PHP
Packer 3.0 JS压缩及混淆工具 下载
2007/05/03 Javascript
json跟xml的对比分析
2008/06/10 Javascript
日期处理的js库(迷你版)--自建js库总结
2011/11/21 Javascript
js快速排序的实现代码
2013/12/08 Javascript
jquery右下角自动弹出可关闭的广告层
2015/05/08 Javascript
JavaScript节点及列表操作实例小结
2015/08/05 Javascript
利用Angular+Angular-Ui实现分页(代码加简单)
2017/03/10 Javascript
AngularJS路由切换实现方法分析
2017/03/17 Javascript
nodejs制作爬虫实现批量下载图片
2017/05/19 NodeJs
vue element中axios下载文件(后端Python)
2019/05/10 Javascript
用Vue.js在浏览器中实现裁剪图像功能
2019/06/18 Javascript
微信小程序 select 下拉框组件功能
2019/09/09 Javascript
JavaScript实现随机五位数验证码
2019/09/27 Javascript
在vue中使用Echarts画曲线图的示例
2020/10/03 Javascript
[56:14]Fnatic vs OG 2018国际邀请赛小组赛BO2 第二场 8.18
2018/08/19 DOTA
python计数排序和基数排序算法实例
2014/04/25 Python
通过python的matplotlib包将Tensorflow数据进行可视化的方法
2019/01/09 Python
Window版下在Jupyter中编写TensorFlow的环境搭建
2020/04/10 Python
Pycharm激活方法及详细教程(详细且实用)
2020/05/12 Python
解析HTML5中的新功能本地存储localStorage
2016/03/01 HTML / CSS
Move Free官方海外旗舰店:美国骨关节健康专业品牌
2017/12/06 全球购物
月度优秀员工获奖感言
2014/08/16 职场文书
党委领导班子整改方案
2014/09/30 职场文书
销售2014年度工作总结
2014/12/08 职场文书
医生个人年度总结
2015/02/28 职场文书
观看建国大业观后感
2015/06/01 职场文书
九九重阳节致辞
2015/07/31 职场文书
企业团队精神心得体会
2016/01/19 职场文书
python3使用diagrams绘制架构图的步骤
2021/04/08 Python
使用react-virtualized实现图片动态高度长列表的问题
2021/05/28 Javascript
Python深度学习之实现卷积神经网络
2021/06/05 Python