代码改变世界

golang 学习笔记 -- slice

2023-08-11 13:57  默默不语  阅读(14)  评论(0编辑  收藏  举报
  1. 函数调用时传递的参数为拷贝的副本, 在函数内部改变参数的值不会影响原变量。但是 golang 中 slice、map、channel、pointer、function 是引用类型,赋值时拷贝的是指针值,对这些变量作出修改时会影响原变量的值。

  2. array(数组)与 slice(切片) 的区别

    1. array
      • 长度固定。在声明时需要指定长度和初值。作为函数参数时,必须指定数组的大小,且传入的数组长度必须与声明的长度一致。
      • 值传递。
    2. slice
      • 动态长度。
      • 引用传递。但作为参数传递到函数中时,若在函数中对 slice 进行扩容(或缩容?)时不会修改外部的 slice 。
  3. slice 声明方式

    • var s []T(只声明,不进行初始化)
      var s []int
      fmt.Println(s == nil) // true
      fmt.Println(s) // []
      fmt.Println(len(s)) // 0
      fmt.Println(cap(s)) // 0
      
    • make([]int, len, cap)
      • cap 为可选参数
      s := make([]int, 2, 5)
      fmt.Println(s == nil) // false
      fmt.Println(s) // [0,0]
      fmt.Println(len(s)) // 2
      fmt.Println(cap(s)) // 5
      
    • 字面量声明
      s := []int{}
      fmt.Println(s == nil) // false
      fmt.Println(s) // []
      fmt.Println(len(s)) // 0
      fmt.Println(cap(s)) // 0
      
  4. slice 的拷贝

    • 赋值给另一个变量
      • 浅拷贝
      • package main
        
        import "fmt"
        
        func main() {
            a := []string{"user1", "user2", "user3"}
            // a 和 b 都指向同一个数组
            b := a
            // slice a 和 slice b 指向相同的地址
            printSlice(a) // len=3 cap=3 address=0xc000120120 [user1 user2 user3]
            printSlice(b) // len=3 cap=3 address=0xc000120120 [user1 user2 user3]
        
            // 删除 b 中的第一个元素
            // len(b) 由 3 变为 2, 但是 cap(b) 不变,依旧为3
            // 原 b[1], b[2] 的值分别赋给 b[0], b[1]
            // 由于是浅拷贝,b[0], b[1] 的修改影响了 a[0], a[1] 的值, 但 a[2] 的值不变
            b = append(b[:0], b[1:]...)
            printSlice(a) // len=3 cap=3 address=0xc0000b0120 [user2 user3 user3]
            printSlice(b) // len=2 cap=3 address=0xc0000b0120 [user2 user3]
        }
        
        func printSlice(s []string) {
            fmt.Printf("len=%d cap=%d address=%p %v\n", len(s), cap(s), s, s)
        }