0
点赞
收藏
分享

微信扫一扫

golang的数组、切片和append一些小点

Go_Viola 2022-01-20 阅读 37
golang

这几天刷题时,总是被切片和append坑了,重新看书后,发现是自己当时对他们认识不到位,重新补充下。

从代码分析:

var arr1  = [3]int{1,2,3}   //定义一个数组,需要在初始化时指定长度
var arr2  = arr1  //将一个数组赋值给另一个数组时,传递的是一份拷贝
arr2[1] = -2
fmt.Println(arr1,arr2) //[1 2 3] [1 -2 3]

// 不指定长度 则为切片
var sli1 = []int{1,2,3}
sli2  := sli1 // 切片是引用类型,切片包装的数组称为该切片的底层数组。
sli2[1] = -2
fmt.Println(sli1,sli2) //[1 -2 3] [1 -2 3]
总结:数组是值类型  切片是引用类型

那么当函数参数传切片的情况, 也一定是引用传递咯?其实不然

func main(){
   xyz := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
   rmLast(xyz)
   fmt.Printf("%v", xyz) //[1 2 3 4 5 6 7 8 9]

   rmLast1(&xyz)
   fmt.Printf("%v", xyz) //[1 2 3 4 5 6 7 8]
}

func rmLast(a []int) { //slice作为函数参数传入函数时,实际上也是拷贝了一份slice
   a = a[:len(a)-1]
}

func rmLast1(a *[]int) {
   *a = (*a)[:len(*a)-1]
}

再看append,通常使用append如下:

sli4 := append(sli3,6,7)

我理所当然的认为,既然append的返回值赋给了新元素,当然不会改变sli3的值,其实不然,准确的说不一定,看两段代码:

//append是一个内置函数,用来在指定的slice后面添加1个或多个元素,并且返回一个新的slice。
var arr3 [5]int  = [5]int{1,2,3,4,5}
sli3 := arr3[:2] // slice3仍然指向arr3
//如果slice的底层数组有足够的空间,那么append函数被调用以后,并不会为新返回的slice分配一个新的数组,而是使用原来的数组。
//这样的话,当改动了新返回的slice以后,原数组也会发生相应的改变。
sli3 = append(sli3,6,7)
fmt.Println(arr3,sli3)  // [1 2 6 7 5] [1 2 6 7]

var arr4 [5]int  = [5]int{1,2,3,4,5}
sli4 := arr3[:2] // slice3仍然指向arr3
//如果原数组中没有足够的空间的情况下,就会分配一个新的数组,那么再对slice做的任何改变,都与原数组没有关系了
sli4 = append(sli4,6,7,8,9,10)
fmt.Println(arr4,sli4)  // [1 2 3 4 5] [1 2 6 7 8 9 10]
总结:如果append以后的元素个数已经超过了切片的容量(即切片的底层数组的容量),就会分配一个新的slice
举报

相关推荐

0 条评论