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

 更新时间:2021年04月26日 14:23:40   作者:书生_AABB  
这篇文章主要介绍了golang中切片copy复制和等号复制的区别,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

结论:

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。

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

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

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

相关文章

  • Go并发编程之goroutine使用正确方法

    Go并发编程之goroutine使用正确方法

    并发编程有一种常见方式就是许多工作子协程都是独立的,互不干扰,但他们又是“同一时间”处理。本文重大给大家介绍Go并发编程goroutine使用方法,一起看看吧
    2021-09-09
  • Golang设计模式之生成器模式讲解和代码示例

    Golang设计模式之生成器模式讲解和代码示例

    生成器是一种创建型设计模式,使你能够分步骤创建复杂对象,与其他创建型模式不同,生成器不要求产品拥有通用接口,这使得用相同的创建过程生成不同的产品成为可能,本文就通过代码示例为大家详细介绍Golang生成器模式,感兴趣的同学可以参考下
    2023-06-06
  • Go语言学习之数组的用法详解

    Go语言学习之数组的用法详解

    数组是相同数据类型的一组数据的集合,数组一旦定义长度不能修改,数组可以通过下标(或者叫索引)来访问元素。本文将通过示例详细讲解Go语言中数组的使用,需要的可以参考一下
    2022-04-04
  • 浅谈Go语言的error类型

    浅谈Go语言的error类型

    这篇文章主要介绍了浅谈Go语言的error类型,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • Go语言操作Excel的实现示例

    Go语言操作Excel的实现示例

    excelize是一个功能丰富且易于使用的Go语言库,它极大地简化了Excel文件的读写操作,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-12-12
  • 深入了解Go语言的基本语法与常用函数

    深入了解Go语言的基本语法与常用函数

    这篇文章主要为大家详细介绍一下Go语言中的基本语法与常用函数,文中的示例代码讲解详细,对我们学习Go语言有一定的帮助,需要的可以参考一下
    2022-07-07
  • Golang内存管理之内存分配器详解

    Golang内存管理之内存分配器详解

    Go内存分配器的设计思想来源于TCMalloc,全称是Thread-Caching Malloc,核心思想是把内存分为多级管理,下面就来和大家深入聊聊Go语言内存分配器的使用吧
    2023-06-06
  • 优雅管理Go Project生命周期

    优雅管理Go Project生命周期

    这篇文章主要为大家介绍了如何优雅的管理Go Project生命周期,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-03-03
  • Golang JSON的进阶用法实例讲解

    Golang JSON的进阶用法实例讲解

    这篇文章主要给大家介绍了关于Golang JSON进阶用法的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用golang具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-09-09
  • Golang中自定义json序列化时间格式的示例代码

    Golang中自定义json序列化时间格式的示例代码

    Go语言作为一个由Google开发,号称互联网的C语言的语言,自然也对JSON格式支持很好,下面这篇文章主要介绍了关于Golang中自定义json序列化时间格式的相关内容,下面话不多说了,来一起看看详细的介绍吧
    2024-08-08

最新评论