// 创建一个字符串切片
// 其长度和容量都是 5 个元素
slice := make([]string, 5)
// 创建一个整型切片
// 其长度为 3 个元素,容量为 5 个元素,容量小于长度的切片会编译出错
slice := make([]int, 3, 5)
slice := []int{10, 20, 30}
// 使用空字符串初始化第 100 个元素
slice := []string{99: ""}
// 创建 nil 整型切片
var slice []int
slice := make([]int, 0)
slice := []int{}
如果在[]运算符里指定了一个值,那么创建的就是数组而不是切片。只有不指定值 的时候,才会创建切片
切片的使用
// 其长度和容量都是 5 个元素
slice := []int{10, 20, 30, 40, 50}
// 其长度为 2 个元素,容量为 4 个元素,该切片不能看见底层数组第0号元素
newSlice := slice[1:3]
// 使用原有的容量来分配一个新元素
// 将新元素赋值为 60
newSlice = append(newSlice, 60)
因为 newSlice 在底层数组里还有额外的容量可用,append 操作将可用的元素合并到切片 的长度,并对其进行赋值。由于和原始的 slice 共享同一个底层数组,slice 中索引为 3 的元 素的值也被改动了
如果切片的底层数组没有足够的可用容量,append 函数会创建一个新的底层数组,将被引用的现有的值复制到新数组里,再追加新的值
综上:创建切片的时候尽量使长度和容量一致,如果增加append新值是新开一个底层数组,而不是直接修改
e.g:
    source := []int{0, 1, 2, 3}
    slice1 := source[0:3]
    fmt.Println(slice1)
    // [0 1 2]
    slice2 := append(slice1, 100)
    slice2[0] = 99
    fmt.Println(slice1)
    fmt.Println(slice2)
    // [99 1 2]
    // [99 1 2 100]
迭代切片
slice := []int{10, 20, 30, 40}
// 迭代每一个元素,并显示其值
for index, value := range slice {
    fmt.Printf("Index: %d Value: %d\n", index, value)
}
如果需要忽略index值,使用下划线占位
当迭代切片时,关键字 range 会返回两个值。第一个值是当前迭代到的索引位置,第二个 值是该位置对应元素值的一份副本
slice := []int{10, 20, 30, 40}
for index, value := range slice {
    // 输出值和地址
    fmt.Printf("Value: %d Value-Addr: %X ElemAddr: %X\n",
        value, &value, &slice[index])
}
//第二种迭代方式
for index := 0; index < len(slice); index++ {
    fmt.Printf("Index: %d Value: %d\n", index, slice[index])
}
关键字 range 总是会从切片头部开始迭代。如果想对迭代做更多的控制,依旧可以使用传 统的 for 循环
多维切片
// 创建一个整型切片的切片
slice := [][]int{{10}, {100, 200}}
// 为第一个切片追加值为 20 的元素
slice[0] = append(slice[0], 20
切片属于引用类型,在函数间传递开销很小
举例理解切片和底层数组
// 长度为3, 容量为5 slice1 := make([]int, 3, 5) // 修改5为3,创建一个长度与容量一致的切片 // 切片所有默认值都是0 slice1[1] = 1 slice1[2] = 2 // 切片2与1共享一个底层数组 slice2 := slice1[0:3] // 在切片2上面增加一个数据 slice3 := append(slice2, 200) // 在切片1上面增加一个数据 slice4 := append(slice1, 100) fmt.Println(slice1) // [0, 1, 2] fmt.Println(slice2) // [0, 1, 2] fmt.Println(slice3) // [0, 1, 2, 100] fmt.Println(slice4) // [0, 1, 2, 100]
再次说明:内置函数 append 会首先使用可用容量。一旦没有可用容量,会分配一个 新的底层数组。这导致很容易忘记切片间正在共享同一个底层数组。一旦发生这种情况,对切片 进行修改,很可能会导致随机且奇怪的问题。对切片内容的修改会影响多个切片,却很难找到问 题的原因。