Go语言学习笔记12.复合类型-切片

切片

先说说数组的缺点:

  • 长度固定
  • 做为参数传递的时候要拷贝整个数组

而切片就是为此诞生的。
切片,简单地说就是将数组切割,只取一部分用。

定义切片

package main //必须有个main包

import "fmt"

func main() {
    array := []int{1, 2, 3, 4, 5} //定义数组
    
    //通过截取数组定义切片
    slice := array[0:3:5] //low:high:max  取low到high-1这几个值,最多取5个  切片长度就是high-low
    fmt.Println(slice)//[1 2 3]
    //slice_1 := array[0:9] //超过长度会报错
    slice_1 := array[0:3] 
    fmt.Println(slice_1)//[1 2 3]
    slice_2 := array[0] 
    fmt.Println(slice_2)//1
    slice_3 := array[:3]//省略low则是0
    fmt.Println(slice_3)//[1 2 3]
    slice_4 := array[3:]//省略high则是max
    fmt.Println(slice_4)//[4 5]

    //直接定义切片
    //slice1 := []int  //这样写不对
    var slice1 []int 
    fmt.Println(slice1)//[]
    slice2 := []int{}
    fmt.Println(slice2)//[]
    slice4 := []int{1, 2, 3} //创建切片并初始化
    fmt.Println(slice4)//[1 2 3]

    slice3 := make([]int, 0 , 5)//类型,len,cap,cap可以省略
    fmt.Println(slice3) //[]
    fmt.Println(len(slice3))//0
    fmt.Println(cap(slice3))//5
}

cap和len的区别

简单点说,len(sli)表示可见元素有几个(即直接打印元素看到的元素个数),而cap(sli)表示所有元素有几个,比如:

arr := []int{2, 3, 5, 7, 11, 13}
sli := arr[1:4]
fmt.Println(sli) //[3 5 7]
fmt.Println(len(sli))//3
fmt.Println(cap(sli))//5

切片和底层数组

同一个数组可以生成多个切片,当修改A切片时,底层数组会直接变,如果B切片刚好引用了同一个地方,则也会被改变。

package main //必须有个main包

import "fmt"

func main() {
    a := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

    s1 := a[2:5] 
    s2 := s1[1:7]

    s1[1] = 666
    fmt.Println("s1 = ", s1) //s1 =  [2 666 4]
    fmt.Println("a = ", a) //a =  [0 1 2 666 4 5 6 7 8 9]

    s2[1] = 777
    fmt.Println("s2 = ", s2) //s2 =  [666 777 5 6 7 8]
    fmt.Println("a = ", a) //a =  [0 1 2 666 777 5 6 7 8 9]

    fmt.Println("s1 = ", s1)//s1 =  [2 666 777]
}

所以可以看出,切片其实是通过指针,取的底层数组的一部分数据。

append

切片还要解决数组长度固定的问题,这个时候就需要append了。

package main //必须有个main包

import "fmt"

func main() {
    //append的覆盖问题
    arr := [5]int{1,2,3,4,5}
    s1 := arr[0:3]
    fmt.Printf("len = %d, cap = %d\n", len(s1), cap(s1))//len = 3, cap = 5
    fmt.Println("s1 = ", s1)//s1 =  [1 2 3]

    s1 = append(s1, 1)
    s1 = append(s1, 2)
    s1 = append(s1, 3)
    fmt.Printf("len = %d, cap = %d\n", len(s1), cap(s1))//len = 6, cap = 10
    fmt.Println("s1 = ", s1) //s1 =  [1 2 3 1 2 3]
    fmt.Println("arr = ", arr)//arr =  [1 2 3 1 2]

    //直接用切片则不存在,此时切片和动态数组差不多
    s2 := []int{1, 2, 3}
    fmt.Println("s2 = ", s2)//s2 =  [1 2 3]
    s2 = append(s2, 5)
    s2 = append(s2, 5)
    s2 = append(s2, 5)
    fmt.Println("s2 = ", s2)//s2 =  [1 2 3 5 5 5]
}

append通常是翻倍扩容的

package main 

import "fmt"

func main() {
    //如果超过原来的容量,通常以2倍容量扩容
    s := make([]int, 0, 1) //容量为1
    oldCap := cap(s)
    for i := 0; i < 20; i++ {
        s = append(s, i)
        if newCap := cap(s); oldCap < newCap {
            fmt.Printf("cap: %d ===> %d\n", oldCap, newCap)
            oldCap = newCap
        }
    }

    /* 输出
        cap: 1 ===> 2
        cap: 2 ===> 4
        cap: 4 ===> 8
        cap: 8 ===> 16
        cap: 16 ===> 32
    */

}

copy

名义上是拷贝,其实就是直接覆盖切片。

package main //必须有个main包

import "fmt"

func main() {
    srcSlice := []int{1, 2}
    dstSlice := []int{6, 6, 6, 6, 6}

    copy(dstSlice, srcSlice)
    fmt.Println("dst = ", dstSlice)//dst =  [1 2 6 6 6]

    srcSlice2 := []int{6, 6, 6, 6, 6}
    dstSlice2 := []int{1, 2}

    copy(dstSlice2, srcSlice2)
    fmt.Println("dst2 = ", dstSlice2)//dst2 =  [6 6]
    
    dstSlice2 = srcSlice2
    fmt.Println("dst2 = ", dstSlice2)//dst2 =  [6 6 6 6 6]
}

切片做参数

package main //必须有个main包

import "fmt"
import "math/rand"
import "time"

func InitData(s []int) {
    //设置种子
    rand.Seed(time.Now().UnixNano())

    for i := 0; i < len(s); i++ {
        s[i] = rand.Intn(100) //100以内的随机数
    }
}

//冒泡排序
func BubbleSort(s []int) {
    n := len(s)

    for i := 0; i < n-1; i++ {
        for j := 0; j < n-1-i; j++ {
            if s[j] > s[j+1] {
                s[j], s[j+1] = s[j+1], s[j]
            }
        }
    }
}

func main() {
    n := 10

    //创建一个切片,len为n
    s := make([]int, n)

    InitData(s) //初始化数组
    fmt.Println("排序前: ", s)

    BubbleSort(s) //冒泡排序
    fmt.Println("排序后: ", s)
}

你可能感兴趣的:(Go语言学习笔记12.复合类型-切片)