• go记录之——slice


    初片是基于数组实现的,它的底层是数组,可以理解为对底层数组的抽象。
    
    • 1

    源码包中src/runtime/slice.go定义了slice的数据结构:

    type slice struct {
    array unsafe.Pointer
    len int
    cap int
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    slice占用24个字节

    array:指向底层数组的指针,占用8个字节
    len:切片的长度,占用8个字节
    cap:切片的容量,cap总是大于等于len 的,占用8个字节
    len(slice)和cap(silce)大小是不一样的


    slice有4种初始化方式

    //初始化方式1:直接声明var slice1 []int
    
    //初始化方式2:使用字面量
    slice2 := []inti1,234}
    
    //初始化方式3:使用make创建slice
    slice3 := make( [ ]int,35)
    
    //初始化方式4:从切片或数组“截取"
    slcie4 := arr[1:3]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    slice的深拷贝和浅拷贝

    深拷贝∶拷贝的是数据本身,创造一个新对象,新创建的对象与原对象不共享内存,新创建的对象在内存中开辟一个新的内存地址,新对象值修改时不会影响原对象值

    实现深拷贝的方式:

    1.copy(slice2, slice1)
    2.遍历append赋值

    func main() {
        slice1 := []int{12345}
        slice2 := make( []int,55)
        fmt.Printf(""slice1: %v,%p", slice1, slice1)
        copy(slice2, slice1)
        fmt.Printf(""slice2: %v,%p", slice2, slice2)
        slice3 := make( []int, 05)
        for _, v := range slice1{
        slice3 = append(slice3,v)
        }
        fmt.Printf(""slice3:%v,%sp",slice3, slice3)
    }
    slice1: [1 2 34 5], oxce000b0030
    slice2: [1 2 34 5], oxc0000b0060
    slice3: [1 2 3 4 5],oxc0000b0090
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    浅拷贝︰拷贝的是数据地址,只复制指向的对象的指针,此时新对象和老对象指向的内存地址是一样的,新对象值修改时老对象也会变化

    实现浅拷贝的方式:

    1.引用类型的变量,默认赋值操作就是浅拷贝

    slice2=slice1
    
    • 1

    2.传参数的时候


    slice扩容机制

    扩容会发生在slice append的时候,当slice的cap不足以容纳新元素,就会进行扩容,扩容规则如下

    1.扩容为2倍的时候会申请新的空间
    2.如果原有slice长度小于1024,那么每次就扩容为原来的2倍
    3.如果原 slice长度大于等于1024,那么每次扩容就扩为原来的1.25倍


    slice为什么不是线程安全

    先看下线程安全的定义:
    多个线程访问同一个对象时,调用这个对象的行为都可以获得正确的结果,那么这个对象就是线程安全的。若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全。

    再看Go语言实现线程安全常用的几种方式:
    1.互斥锁
    2.读写锁
    3.原子操作
    4. sync.once
    5.sync.atomic
    6.channel

    slice底层结构并没有使用加锁等方式,不支持并发读写,所以并不是线程安全的,使用多个gorcutine对类型为 slice的变量进行操作,每次输出的值大概率都不会一样,与预期值不一致; slice在并发执行中不会报错,但是数据会丢失

  • 相关阅读:
    Python之wxPython事件处理
    信息熵原理与Python实现
    AI短视频矩阵运营软件|抖音视频矩阵控制工具
    数据在内存中的存储(1)
    医学之细胞组织基因(完整)
    漫谈AI 时代的信息模型
    8.Vue3虚拟节点的实现
    MySQL识别不了中文怎么办?(适合新手)
    线程创建之线程池
    AntD上传文件 结合Axios 服务端由Spring MVC接收
  • 原文地址:https://blog.csdn.net/qq_52563729/article/details/126082139