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 相关文章推荐
一文读懂go中semaphore(信号量)源码
Apr 03 Golang
go语言中切片与内存复制 memcpy 的实现操作
Apr 27 Golang
golang 如何用反射reflect操作结构体
Apr 28 Golang
解决go在函数退出后子协程的退出问题
Apr 30 Golang
Golang之sync.Pool使用详解
May 06 Golang
Golang Gob编码(gob包的使用详解)
May 07 Golang
基于Go语言构建RESTful API服务
Jul 25 Golang
Go 中的空白标识符下划线
Mar 25 Golang
Go归并排序算法的实现方法
Apr 06 Golang
golang的文件创建及读写操作
Apr 14 Golang
Golang 并发编程 SingleFlight模式
Apr 26 Golang
在ubuntu下安装go开发环境的全过程
Aug 05 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
简单示例AJAX结合PHP代码实现登录效果代码
2008/07/25 PHP
PHP中的闭包(匿名函数)浅析
2015/02/07 PHP
PHP保留两位小数的几种方法
2019/07/24 PHP
由点击页面其它地方隐藏div所想到的jQuery的delegate
2013/08/29 Javascript
jquery阻止冒泡事件使用模拟事件
2013/09/06 Javascript
Javascript 命名空间模式
2013/11/01 Javascript
JQuery each()嵌套使用小结
2014/04/18 Javascript
将HTML的左右尖括号等转义成实体形式的两种实现方式
2014/05/04 Javascript
第五章之BootStrap 栅格系统
2016/04/25 Javascript
BootStrap入门教程(二)之固定的内置样式
2016/09/19 Javascript
JavaScript中捕获与冒泡详解及实例
2017/02/03 Javascript
ES5学习教程之Array对象
2017/04/01 Javascript
jquery中$.fn和图片滚动效果实现的必备知识总结
2017/04/21 jQuery
bootstrap精简教程_动力节点Java学院整理
2017/07/14 Javascript
基于bootstrap实现多个下拉框同时搜索功能
2017/07/19 Javascript
基于jQuery ztree实现表格风格的树状结构
2018/08/31 jQuery
Node.js + express实现上传大文件的方法分析【图片、文本文件】
2019/03/14 Javascript
React路由鉴权的实现方法
2019/09/05 Javascript
使用Python绘制图表大全总结
2017/02/11 Python
python利用requests库进行接口测试的方法详解
2018/07/06 Python
Linux下Pycharm、Anaconda环境配置及使用踩坑
2018/12/19 Python
django 2.2和mysql使用的常见问题
2019/07/18 Python
Python统计学一数据的概括性度量详解
2020/03/03 Python
python让函数不返回结果的方法
2020/06/22 Python
Python DES加密实现原理及实例解析
2020/07/17 Python
美国网上订购鲜花:FTD
2016/09/23 全球购物
Luxplus瑞典:香水和美容护理折扣
2018/01/28 全球购物
.net笔试题
2014/03/03 面试题
项目经理岗位职责
2013/11/11 职场文书
小学六一儿童节活动方案
2014/08/27 职场文书
财务出纳岗位职责
2015/03/31 职场文书
客服专员岗位职责范本
2015/04/07 职场文书
建党伟业的观后感
2015/06/01 职场文书
《坐井观天》教学反思
2016/02/18 职场文书
详解Python requests模块
2021/06/21 Python
css 边框添加四个角的实现代码
2021/10/16 HTML / CSS