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如何去除多余空白字符(含制表符)
Apr 25 Golang
Go语言切片前或中间插入项与内置copy()函数详解
Apr 27 Golang
go语言中json数据的读取和写出操作
Apr 28 Golang
golang 实现Location跳转方式
May 02 Golang
解决golang结构体tag编译错误的问题
May 02 Golang
基于Golang 高并发问题的解决方案
May 08 Golang
浅谈Go语言多态的实现与interface使用
Jun 16 Golang
Go语言实现Base64、Base58编码与解码
Jul 26 Golang
如何解决goland,idea全局搜索快捷键失效问题
Apr 03 Golang
Golang日志包的使用
Apr 20 Golang
Golang 结构体数据集合
Apr 22 Golang
Go gRPC进阶教程gRPC转换HTTP
Jun 16 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 google或baidu分页代码
2009/11/26 PHP
PHP中防止SQL注入攻击和XSS攻击的两个简单方法
2010/04/15 PHP
深入探讨<br />和 \r\n两者有什么区别??
2013/06/05 PHP
php判断/计算闰年的方法小结【三种方法】
2019/07/06 PHP
javascript 一个自定义长度的文本自动换行的函数
2007/08/19 Javascript
仿淘宝TAB切换搜索框搜索切换的相关内容
2014/09/21 Javascript
node.js中的fs.readlinkSync方法使用说明
2014/12/17 Javascript
javascript截取字符串小结
2015/04/28 Javascript
JavaScript生成福利彩票双色球号码
2015/05/15 Javascript
jQuery鼠标经过方形图片切换成圆边效果代码分享
2015/08/20 Javascript
angularjs ocLazyLoad分步加载js文件实例
2017/01/17 Javascript
nodejs中全局变量的实例解析
2017/03/07 NodeJs
基于iScroll实现下拉刷新和上滑加载效果
2017/07/18 Javascript
vue watch自动检测数据变化实时渲染的方法
2018/01/16 Javascript
vue 实现在函数中触发路由跳转的示例
2018/09/01 Javascript
每个 JavaScript 工程师都应懂的33个概念
2018/10/22 Javascript
Webpack 4如何动态切割JS注入文件名详解
2019/07/09 Javascript
javascript绘制简单钟表效果
2020/04/07 Javascript
python实现文件名批量替换和内容替换
2014/03/20 Python
python的faker库用法
2019/11/28 Python
python 子类调用父类的构造函数实例
2020/03/12 Python
工程师必须了解的LRU缓存淘汰算法以及python实现过程
2020/10/15 Python
css 如何让背景图片拉伸填充避免重复显示
2013/07/11 HTML / CSS
草莓网美国官网:Strawberrynet USA
2016/12/11 全球购物
全球最大的瓷器、水晶和银器零售商:Replacements
2020/06/15 全球购物
const char*, char const*, char*const的区别是什么
2014/07/09 面试题
常用UNIX 命令(Linux的常用命令)
2015/12/26 面试题
军训心得体会
2013/12/31 职场文书
党支部书记先进事迹
2014/01/17 职场文书
领导失职检讨书
2014/02/24 职场文书
机关副主任个人四风问题整改措施
2014/09/26 职场文书
作风整顿剖析材料
2014/09/30 职场文书
公证书格式
2015/01/23 职场文书
统计员岗位职责
2015/02/11 职场文书
2015年技术员工作总结
2015/04/10 职场文书
python实战之用emoji表情生成文字
2021/05/08 Python