切片(slice)

切片是动态数组,比数组灵活。数组长度不可变,但是切片可以追加。 切片原型定义如下:

struct Slice
{
  byte *array;
  unit32 len;
  unit32 cap;
};

它抽象为以下三个部分:
1. 指向被引用的底层数组的指针;
2. 切片中元素的个数;
3. 切片分配的存储空间。

声明、定义和初始化

声明一个切片:

var sliceTest []int
  • 声明的切片是nil,不初始化无法插入数据
  • 跟map一样,通过make定义切片
make([]T, length, capacity)
  • length为初始长度,为必须参数。capacity为指定容量,可选。
    例如:
sliceTest = make([]int, 10)
  • 直接初始化切片
sliceTest1 := [] int {1,2,3}
  • 引用赋值

s := arr[startIndex:endIndex]

初始化s,是arr从startIndex到endIndex的引用

s := sliceTest1[:]//s表示sliceTest的引用
s1 := sliceTest[1]

append

  • append主要用于给某个切片(slice)追加元素
  • 如果该切片存储空间(cap)足够,就直接追加,长度(len)变长;如果空间不足,就会重新开辟内存,并将之前的元素和新的元素一同拷贝进去
  • 第一个参数为切片,后面是该切片存储元素类型的可变参数

代码例子

package main

import (
    "fmt"
)

func main(){
    var sliceTest []int
    //声明的切片是nil
    if sliceTest == nil {
        fmt.Println("slice is nil")
    }
    //用make创建切片,制定默认长度
    sliceTest = make([]int, 2)
    sliceTest[0] = 1
    fmt.Printf("len:%d, cap:%d\n", len(sliceTest), cap(sliceTest))
    sliceTest[1] = 2
    //通过range遍历切片
    for i, v := range sliceTest{
        fmt.Printf("index:%d, value:%d\n", i, v)
    }
    //切片默认长度是2,不能直接通过下标增加长度
    //sliceTest[2] = 2 //程序崩溃,提示"panic: runtime error: index out of range"
    //sliceTest[3] = 3
    //通过append添加元素到切片中
    sliceTest = append(sliceTest, 3)
    fmt.Printf("len:%d, cap:%d\n", len(sliceTest), cap(sliceTest))//第一次append将cap增加了2
    sliceTest = append(sliceTest, 4)
    fmt.Printf("len:%d, cap:%d\n", len(sliceTest), cap(sliceTest))//第二次append,因为还有空间,cap没增加
    for i := 0; i < len(sliceTest); i++ {
        fmt.Printf("index:%d, value:%d\n", i, sliceTest[i])
    }

    s := sliceTest[:]//s引用sliceTest
    fmt.Printf("s, len:%d, cap:%d\n", len(s), cap(s))
    for i := 0; i < len(s); i++ {
        fmt.Printf("s, index:%d, value:%d\n", i, s[i])
    }

    s1 := s[2:4]//s1引用s下标2-4的元素(不包含下标4)
    fmt.Printf("s1, len:%d, cap:%d\n", len(s1), cap(s1))
    for i := 0; i < len(s1); i++ {
        fmt.Printf("s1, index:%d, value:%d\n", i, s1[i])
    }
    s1[1] = 14 //改变s1中的值
    for i := 0; i < len(sliceTest); i++ {
        fmt.Printf("sliceTest, index:%d, value:%d\n", i, sliceTest[i])//因为切片是引用类型,所以修改会反应到sliceTest中
    }
    s2 := s[:2]
    fmt.Printf("s2, len:%d, cap:%d\n", len(s2), cap(s2))
    for i := 0; i < len(s2); i++ {
        fmt.Printf("s2, index:%d, value:%d\n", i, s2[i])
    }
    s2 = append(s2, 23)//s2的cap=4,len=2,空间充足,直接追加
    fmt.Printf("s2, len:%d, cap:%d\n", len(s2), cap(s2))
    for i := 0; i < len(sliceTest); i++ {//sliceTest跟s2指向同一个slice,所以
        fmt.Printf("sliceTest, index:%d, value:%d\n", i, sliceTest[i])
    }
    s2 = append(s2, 24)
    fmt.Printf("s2, len:%d, cap:%d\n", len(s2), cap(s2))
    for i := 0; i < len(sliceTest); i++ {
        fmt.Printf("sliceTest, index:%d, value:%d\n", i, sliceTest[i])
    }
    for i := 0; i < len(s2); i++ {
        fmt.Printf("s2, index:%d, value:%d\n", i, s2[i])
    }

    s3 := append(s2, 25, 26, 27)//s2继续添加,因为容量不够,所以要从新分配内存,将之前的元素copy过去,再赋值给s3。此时s2没有变,还是sliceTest的引用
    s2[0] = 21//此时更改s2[0],会更改到sliceTest[0]
    s3[0] = 31//此时更改s3[0],不会更改到sliceTest[0]
    fmt.Printf("s2, len:%d, cap:%d\n", len(s2), cap(s2))
    fmt.Printf("s3, len:%d, cap:%d\n", len(s3), cap(s3))
    for i := 0; i < len(sliceTest); i++ {
        fmt.Printf("sliceTest, index:%d, value:%d\n", i, sliceTest[i])
    }
    for i := 0; i < len(s2); i++ {
        fmt.Printf("s2, index:%d, value:%d\n", i, s2[i])
    }
    for i := 0; i < len(s3); i++ {
        fmt.Printf("s3, index:%d, value:%d\n", i, s3[i])
    }

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值