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 生成对应的数据表struct定义操作
Apr 28 Golang
Golang 如何实现函数的任意类型传参
Apr 29 Golang
使用golang编写一个并发工作队列
May 08 Golang
Go语言设计模式之结构型模式
Jun 22 Golang
go select编译期的优化处理逻辑使用场景分析
Jun 28 Golang
go goroutine 怎样进行错误处理
Jul 16 Golang
如何解决goland,idea全局搜索快捷键失效问题
Apr 03 Golang
Golang 并发编程 SingleFlight模式
Apr 26 Golang
Golang实现可重入锁的示例代码
May 25 Golang
详解Go语言中Get/Post请求测试
Jun 01 Golang
Go语言测试库testify使用学习
Jul 23 Golang
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
一个阿拉伯数字转中文数字的函数
2006/10/09 PHP
PHP获取当前页面完整URL的实现代码
2013/06/10 PHP
thinkphp修改配置进入默认首页的方法
2017/02/07 PHP
swoole_process实现进程池的方法示例
2018/10/29 PHP
PDO::prepare讲解
2019/01/29 PHP
LBS blog sql注射漏洞[All version]-官方已有补丁
2007/08/26 Javascript
javascript vvorld 在线加密破解方法
2008/11/13 Javascript
js与运算符和或运算符的妙用
2014/02/14 Javascript
node.js中的buffer.Buffer.byteLength方法使用说明
2014/12/10 Javascript
jQuery判断一个元素是否可见的方法
2015/06/05 Javascript
JS使用cookie实现DIV提示框只显示一次的方法
2015/11/05 Javascript
JavaScript判断按钮被点击的方法
2015/12/13 Javascript
jquery ui dialog替代confirm实例分析
2016/01/25 Javascript
基于jQuery实现多标签页切换的效果(web前端开发)
2016/07/24 Javascript
jQuery 判断元素整理汇总
2017/02/28 Javascript
基于Vue实例生命周期(全面解析)
2017/08/16 Javascript
Vue Router的懒加载路径的解决方法
2018/06/21 Javascript
如何基于vue-cli3.0构建功能完善的移动端架子
2019/04/24 Javascript
原生js实现下拉选项卡
2019/11/27 Javascript
浅谈vue中$event理解和框架中在包含默认值外传参
2020/08/07 Javascript
[44:40]Spirit vs Navi Supermajor小组赛 A组败者组第一轮 BO3 第一场 6.2
2018/06/03 DOTA
Python模块学习 filecmp 文件比较
2012/08/27 Python
Python解决N阶台阶走法问题的方法分析
2017/12/28 Python
对python文件读写的缓冲行为详解
2019/02/13 Python
pandas DataFrame 警告(SettingWithCopyWarning)的解决
2019/07/23 Python
Python 点击指定位置验证码破解的实现代码
2019/09/11 Python
Pycharm和Idea支持的vim插件的方法
2020/02/21 Python
30行Python代码实现高分辨率图像导航的方法
2020/05/22 Python
详解canvas.toDataURL()报错的解决方案全都在这了
2020/03/31 HTML / CSS
巴西在线鞋店:Shoestock
2017/10/28 全球购物
美国礼品卡交易网站:Cardpool
2018/08/27 全球购物
Allen Edmonds官方网站:一家美国优质男士鞋类及配饰制造商
2019/03/12 全球购物
五一劳动节活动记录
2014/03/23 职场文书
个人党性锻炼总结
2015/03/05 职场文书
python opencv常用图形绘制方法(线段、矩形、圆形、椭圆、文本)
2021/04/12 Python
Win11应用商店打开闪退怎么解决? win11应用商店打不开的多种解决办法
2022/04/05 数码科技