定义切片(slice):

    1. func main() {
    2. arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7} // 数组
    3. // 切片
    4. fmt.Println(arr[2:6])
    5. fmt.Println(arr[:6])
    6. fmt.Println(arr[2:])
    7. fmt.Println(arr[:])
    8. // [2 3 4 5]
    9. // [0 1 2 3 4 5]
    10. // [2 3 4 5 6 7]
    11. // [0 1 2 3 4 5 6 7]
    12. }

    切片本身没有数据,是对底层数组的视图(view):

    func updateSlice(s []int) { // 切片是对数组的视图,可以通过切片来改变数组
        s[0] = 100
    }
    func main() {
        arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7} // 数组
    
        // 切片
        s1 := arr[2:]
        s2 := arr[:]
    
        updateSlice(s1) 
        fmt.Println(s1)  // [100 3 4 5 6 7]
        fmt.Println(arr) // [0 1 100 3 4 5 6 7]
    
        updateSlice(s2)
        fmt.Println(s2) // [100 1 100 3 4 5 6 7]
        fmt.Println(arr) // [100 1 100 3 4 5 6 7]
    }
    
    func printArray(arr []int) { // 此时传入的是切片,不是数组
        arr[0] = 100
        for i, v := range arr {
            fmt.Println(i, v)
        }
    }
    
    func main() {
        printArray(arr1[:])
        printArray(arr3[:])
        fmt.Println(arr1, arr3)
        // [100 0 0 0 0] [100 4 6 8 10]
    }
    

    reslice操作(对切片再取切片):

    func main() {
        arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7} // 数组
    
        // 切片
        s2 = arr[:]
        fmt.Println(s2) // [100 1 100 3 4 5 6 7]
        // reslice
        s2 = s2[:5]
        fmt.Println(s2) // [100 1 100 3 4]
        s2 = s2[2:]
        fmt.Println(s2) // [100 3 4]
    }
    

    slice的扩展:

    func main() {
        arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7} // 数组
    
        s1 := arr[2:6]
        s2 := s1[3:5]
        fmt.Printf("s1=%v, len(s1)=%d, cap(s1)=%d\n", s1, len(s1), cap(s1)) // [2 3 4 5], 4, 6
        fmt.Println(s1[4]) // 报错
        fmt.Printf("s2=%v, len(s2)=%d, cap(s2)=%d\n", s2, len(s2), cap(s2)) 
        // [5 6], 2, 3
        // 此处Slice进行了向后扩展(只能向后扩展,不能向前扩展)
        fmt.Println(s1[3:6]) // [5 6 7]
    }
    

    image.png
    image.png
    slice是一个底层array的视图,其内部包含三个变量:
    ptr : 指向array中slice开头的元素
    len : slice的长度
    cap : array中从ptr开始到结束的长度
    使用s[i]进行索引不能超越len;
    向后扩展可以超越len,但不能超越cap

    向slice添加元素:
    添加元素时如果超越cap,系统会重新分配更大的底层数组
    由于值传递的关系,在使用append函数时必须接收append的返回值:
    s = append(s, val)

    func main() {
        arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7} // 数组
    
        s1 := arr[2:6]
        s2 := s1[3:5] // [5 6]
        s3 := append(s2, 10) // [5 6 10]
        s4 := append(s3, 11) // [5 6 10 11]
        s5 := append(s4, 12) // [5 6 10 11 12]
        // 因为添加元素时超越了cap,s4和s5不再是arr的view,而是view了一个新的数组
        fmt.Println(arr) // [0 1 2 3 4 5 6 10]
    }
    

    创建slice:

    import "fmt"
    
    func printSlice(s []int) {
        fmt.Printf("%v, len=%d, cap=%d\n", s, len(s), cap(s))
    }
    
    func main() {
        // 创建方式1:先定义,再初始化
        var s []int // zero value for slice is nil
    
        for i := 0; i < 100; i++ {
            printSlice(s)
            s = append(s, 2 * i + 1)
        }
        // 创建方式2:定义的同时初始化
        // 该语句先创建array[2 4 6 8], 然后创建slice s1去view这个array
        s1 := []int{2, 4, 6, 8}
        printSlice(s1) // [2 4 6 8], len=4, cap=4
    
        // 创建方式3:指定len
        s2 := make([]int, 16)
        printSlice(s2) // [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0], len=16, cap=16
    
        // 创建方式4: 指定len和cap
        s3 := make([]int, 10, 32)
        printSlice(s3) // [0 0 0 0 0 0 0 0 0 0], len=10, cap=32
    }
    

    其他操作:

    func main() {
        s1 := []int{2, 4, 6, 8}
        printSlice(s1) // [2 4 6 8], len=4, cap=4
    
        s2 := make([]int, 16)
        printSlice(s2) // [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0], len=16, cap=16
    
        s3 := make([]int, 10, 32)
        printSlice(s3) // [0 0 0 0 0 0 0 0 0 0], len=10, cap=32
    
        // copy slice
        copy(s2, s1)
        printSlice(s2) // [2 4 6 8 0 0 0 0 0 0 0 0 0 0 0 0], len=16, cap=16
    
        // deleting elements from slice
        s2 = append(s2[:3], s2[4:]...)
        printSlice(s2) // [2 4 6 0 0 0 0 0 0 0 0 0 0 0 0], len=15, cap=16
    
        // popping from front
        front := s2[0]
        s2 = s2[1:]
        fmt.Println(front) // 2
        printSlice(s2) // [4 6 0 0 0 0 0 0 0 0 0 0 0 0], len=14, cap=15
    
        // popping from back
        tail := s2[len(s2)-1]
        s2 = s2[:len(s2)-1]
        fmt.Println(tail) // 0
        printSlice(s2) // [4 6 0 0 0 0 0 0 0 0 0 0 0], len=13, cap=15
    }