要一直走下去

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

切片的本质:

切片是一个引用类型,是基于数组类型做的一层封装,内部结构包含头部指针、长度、容量。 

形象把切片理解一个“框” ,框住数组或map的一部分,只能框连续的元素,底层数组改了,切片也改了,切片可以再切片

切片长度 len(slice) 是切片框住的元素个数;切片的容量 cap(slice) 是底层数组从切片的第一个元素到最后一个元素的数量
切片支持自动扩容,里面的元素类型固定
切片之间是不能用==比较的,切片唯一合法的比较操作是和nil比较。判断切片是否为空要用len(slice) == 0来判
一个nil值的切片并没有底层数组,一个nil值的切片的长度和容量都是0,但是一个长度和容量都是0的切片不一定是nil

声明切片:

var name []int     // name==nil 为 true

切片初始化(若不初始化,切片=nil)

    s1 := []string{"哈哈", "呵呵"}   //底层初始化一个长度为2,容量为2的数组包装后返回

    s1 := make([]int, 5, 10)    //创建长度5容量10的切片,底层数组前5个元素为0,可以从第6个元素开始追加

    s2 := make([]int, 0, 10)   //创建长度0容量10的切片,长度为0有什么意义? append的时候从下标0开始追加

    s2 := make([]int, 5)    //如果不写容量,容量与长度一样

    //由数组得到切片
    a1 := [...]int{0, 2, 3, 43, 6, 534, 32, 21, 23}

    s1 := a1[0:4]       //[0,2,3,43]

    s2 := a1[:4]      //a1[0:4]

    s3 := a1[3:]      //a1[3:len(a1)]

    s4 := a1[:]       //a1[0:len(a1)]

切片追加元素(扩容)

    s1 := []string{"bj","sh","sz"}   //长度=3,容量=3
 
    // 调用append函数追加。必须用原来的切片变量接收返回值,若追加元素超过容量,底层数组变了
    s1 = append(s1, "gz") 
 
    //追加多个元素。操作之后,长度=3,容量=6
    s1 = append(s1, "hz", "cd")
 
    //批量增加ss的元素到s1中
    ss := []string{"wh", "xa", "sz"}
    s1 = append(s1, ss...)  //"..."表示拆开

扩容逻辑:

if  申请容量>2倍旧容量  最终容量=申请容量
elif  旧切片长度<1024    最终容量=2倍旧容量
elif  旧切片长度>=1024  最终容量=旧容量+1/4
else 最终容量计算值溢出 最终容量=申请容量

使用copy()函数复制切片:

s1 := []int{1,3,5}
s2 := s1 //赋值,是引用赋值
var s3 = make([]int, 3)
copy(s3, s1)   // copy成了两份

切片中删除元素

    //没有封装好的删除元素的方法
    x1 := [...]int{1,3,5}   //定义数组
    s1 := x1[:]             //切片
    fmt.Println(s1, len(s1), cap(s1))    //[1,3,5]  3  3
    s1 = append(s1[:1], s1[2:]...)    //删除下标为1的元素,容量还是3
    fmt.Println(s1, len(s1), cap(s1)) //[1,5] 2 3
    fmt.Println(x1)  //[1,5,5]

 

切片遍历:

    for i:=0;i<len(slice); i++{
        fmt.Println(s3[i])
    }
    
    for i,v := range slice{
        fmt.Println(i,v)
    }

 

posted on 2020-07-01 18:29  要一直走下去  阅读(144)  评论(0编辑  收藏  举报