天天看點

Go語言中 數組和slice 走過的坑

數組和slice差別

在go語言中,數組是一段連續的記憶體,在初始化時候需要明确聲明其大小,不可以在運作時動态生成,而slice則可以自由得伸縮其大小。我們知道slice,底層其實就是一個數組。

指派差別

數組指派

go語言中,數組指派采用的是值指派方式,指派後的兩個數組互不影響

func arrayFuzhi(){
   array1 := [3][3]int{{1,2,3},{4,5,6},{7,8,9}}
   array2 := array1
   array1[0][0]=0
   fmt.Printf("array1 address:%p,array1[0][0]:%d\n",&array1,array1[0][0])
   fmt.Printf("array2 address:%p,array2[0][0]:%d",&array2,array2[0][0])
}
           

運作結果

array1 address:0xc00000c1e0,array1[0][0]:0
array2 address:0xc00000c230,array2[0][0]:1
           

很明顯,兩個數組不受任何影響

slice指派

go語言中,slice指派采用的是位址指派方式,指派後的兩個slice使用的是同一個slice,指向同一個底層數組

func sliceFuzhi(){
   array1 := [][]int{{1,2,3},{4,5,6},{7,8,9}}
   array2 := array1
   array1[0][0]=0
   fmt.Printf("array1 address:%p,array1[0][0]:%d\n",array1,array1[0][0])
   fmt.Printf("array2 address:%p,array2[0][0]:%d",array2,array2[0][0])
}
           

運作結果

array1 address:0xc00003a050,array1[0][0]:0
array2 address:0xc00003a050,array2[0][0]:0
           

很明顯,兩個slice的位址是一樣的,并且修改一個值,會影響另外一個slice。

slice複制

一維數組

現在我們有個需求,就是把現有的slice進行複制,并且讓兩個slice無影響,此時我們可以使用go内置函數copy來實作。

func sliceCopy(){
   array1 := []int{1,2,3}
   array2 := make([]int,len(array1))
   array1[0]=99
   fmt.Printf("array1 address:%p,array1[0]:%d\n",array1,array1[0])
   fmt.Printf("array2 address:%p,array2[0]:%d",array2,array2[0])
}
           

運作結果

array1 address:0xc00009e140,array1[0]:99
array2 address:0xc00009e160,array2[0]:1
           

很明顯,兩個slice的位址是不一樣的,并且修改一個值,不會影響另外一個slice。

多元數組

以上是一維數組的複制,如果是二維或多元數組,則不生效,因為二維數組的裡面的一維數組還是slice,需要重新copy,是以,針對于二維數組,我們可以周遊源slice的每個元素,并添加到新的數組上去。

func sliceCopy_erwei(){
	array1 := [][]int{{1,2,3},{4,5,6},{7,8,9}}
	var array2 [][]int
	for i:=0;i<len(array1);i++{
		tmp:=make([]int,len(array1[i]))
		copy(tmp,array1[i])
		array2=append(array2,tmp)
	}
	array1[0][0]=99
	fmt.Printf("array1 address:%p,array1[0][0]:%d\n",&array1[0][0],array1[0][0])
	fmt.Printf("array2 address:%p,array1[0][0]:%d",&array2[0][0],array2[0][0])
}
           

運作結果

array1 address:0xc00009e140,array1[0][0]:99
array2 address:0xc00009e1a0,array1[0][0]:1