Golang切片笔记 | 青训营

55 阅读2分钟

定义切片

var slice []int  //一个无长度的数组
slice := []int{1,2,3}  //初始化切片,len和cap为3
slice := make([]int, 3, 4)。//初始化一个len为3 cap为4的切片

arr := [4]int{1,2,3,4}
slice := arr[:3]  // 此切片len和cap为3,值为{1,2,3}

slice底层机制

当slice作为参数时,go会对传入的slice进行复制然后传入函数

func changeSlice(a []int) {
    a[3] = 6
}

func main() {
    arr := [4]int{1,2,3,4}
	slice := arr[:4]
    changeSlice(slice)
    fmt.Println(arr)
}

//结果:{1,2,3,6}

在上面的例子中,changeSlice函数改变了传入切片的值,但是arr的值却改变了。说明slice以及传入的参数底层都指向arr的内存空间。

只有当slice的容超出底层数组的长度时,slice指向的内存空间才会改变,此时slice会指向一块新开辟的数组。

func changeSlice(a []int) {
    a = append(a, 6) //这里因为切片的长度超出了arr数组的长度,切片a会指向一块新的数组
    a[3] = 5
    fmt.Println(a)
}

func main() {
    arr := [4]int{1,2,3,4}
	slice := arr[:4]
    changeSlice(slice)
    fmt.Println(arr, slice)
}

//结果:{1,2,3,5,6}, {1,2,3,4}, {1,2,3,4}
  • 注意:如果切片的长度没有超出底层数组的长度,则使用append会改变底层数组的值:
func changeSlice(a []int) {
    a = append(a, 6) //这里因为切片的长度没有超出arr的长度
    a[3] = 5
    fmt.Println(a)
}

func main() {
    arr := [5]int{1,2,3,4,5}
	slice := arr[:3]
    changeSlice(slice)
    fmt.Println(arr, slice)
}

//结果:{1,2,3,5,6}, {1,2,3,5,6}, {1,2,3,5}

如果想要给切片开辟一块新空间还可以使用以下方法:

	arr := [5]int{1, 2, 3, 4, 5}
	slice2 := append([]int{}, arr[:4]...)
	arr[3] = 6
	fmt.Println(slice2)

//结果 {1,2,3,4}

用 append(空切片, 目标切片) 的方法可以使切片指向一个新开辟的数组空间。这样slice的值就不会受到原数组的影响了。