1.使用方式
數組和slice長的很像,操作方式也都差不多,並且slice包含了數組的基本的操作方式,如下標、range循環,還有一些如len()則是多種類型共用,所以根據操作根本搞不清數組和切片的區別,能夠看出區別的地方主要看如何聲明的。
數組的聲明方式很單一,通常就是下面這樣:
array1 := [5]int{1, 2, 3, 4, 5} array2 := [5]int{}
slice的聲明方式就非常多樣了,如前面介紹的幾種:
var slice1 = []int{1, 2, 3, 4, 5} var slice2 = make([]int, 0, 5) var slice3 = make([]int, 5, 5) var slice4 = make([]int, 5)
加上對數組的切片和append操作都會產生數組切片(slice)
2.值傳遞or引用傳遞
func arrayModify(array [5]int) { newArray := array newArray[0] = 88 } func sliceModify(slice []int) { newSlice := slice newSlice[0] = 88 } func main() { array := [5]int{1, 2, 3, 4, 5} slice := []int{1, 2, 3, 4, 5} arrayModify(array) sliceModify(slice) fmt.Println(array) fmt.Println(slice) }
輸出
[1 2 3 4 5] [88 2 3 4 5]
其實不只是數組,go語言中的大多數類型在函數中當作參數傳遞都是值語義的。也就是任何值語義的一種類型當作參數傳遞到調用的函數中,都會經過一次內容的copy,從一個方法棧中copy到另一個方法棧。這對於熟練java的同學需要進行一次徹底的觀念轉變,在java中除了少數的值類型是按照值傳遞,所有的類在函數傳遞時都是具有引用語義的,也就是通過指針傳遞。所以在使用時傳遞對象,不需要去分別值和引用。
go說到底不是一種純粹的面向對象的語言,更多的是一種更簡單高效的C,所以在參數傳遞上跟C保持着基本的一致性。一些較大的數據類型,比如結構體、數組等,最好使用傳遞指針的方式,這樣就能避免在函數傳遞時對數據的copy。
雖然slice在傳遞時是按照引用語義傳遞,但是又因為append()操作的問題,導致即使是引用傳遞還是不能順利解決一些問題,后面一篇文章將說明一下如何解決遞歸函數中傳遞slice的問題: