數組切片slice這個東西看起來很美好,真正用起來會發現有諸多的不爽。java
第一,數組、數組切片混淆不清,使用方式徹底同樣,有時候一些特性又徹底不同,搞不清原理很容易誤使用。數組
第二,數組切片的append操做,每次對slice append操做,都返回一個新的slice的引用,對slice的引用無法保持,這樣在函數傳遞slice的狀況下append,在調用函數的上下文中看不到slice append的效果。若是想要這種方式湊效,不得不另闢蹊徑。本文主要說一下如何解決這個窘境的方法。app
函數傳遞slice存在什麼問題?函數
func sliceModify(slice []int) { // slice[0] = 88 slice = append(slice, 6) } func main() { slice := []int{1, 2, 3, 4, 5} sliceModify(slice) fmt.Println(slice) }
輸出:spa
[1 2 3 4 5]
問題所在:設計
雖說數組切片在函數傳遞時是按照引用的語義傳遞的,好比說在sliceModify函數裏面slice[0] = 88,在方法調用的上下文中,調用函數對slice引用的改表是看得見的。指針
可是在對slice進行append操做的時候,咱們驚奇的發現,此次又無論用了。緣由就是append操做會返回這個擴展了的slice的引用,必須讓原引用從新賦值爲新slice的引用,說白了就是,傳遞過來的這個指針原來指了內存中的A區域,A區域是原數組的真正所在。通過一次 append以後,要把這個指針改成指向B,B對應append後新的slice的引用。可是方法調用的上下文裏的slice指針仍是指向了老的A內存區域。code
這個邏輯實在有些奇葩,這裏我不得再也不次吐槽append的設計。有人說這個問題好解決啊,只須要在sliceModify函數的返回值中把append後新的slice引用返回就行了。這樣作固然是能夠滴,可是像遞歸調用的函數就很差解決了。blog
下面就說一下這個問題的解決辦法,方法也很簡單,就是傳遞指針的指針。雖然有些繞,可是總算把問題解決了。固然也有其餘的辦法,好比按照java等語言的方式,本身實現一個ArrayList,在對可變數組擴展的時候,千萬表改變引用了。遞歸
func sliceModify(slice *[]int) { *slice = append(*slice, 6) } func main() { slice := []int{1, 2, 3, 4, 5} sliceModify(&slice) fmt.Println(slice) }
此次就能夠輸出預期的結果了:
[1 2 3 4 5 6]
遞歸調用的例子:
func insertTo10(arr *[]int) { length := len(*arr) if length == 10 { return } *arr = append(*arr, length) insertTo10(arr) } func main() { arr10 := []int{} insertTo10(&arr10) fmt.Println(arr10) }
還能夠訪問我樹莓派上搭的博客地址: