go遞歸函數如何傳遞數組切片slice

數組切片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)
}

 

還能夠訪問我樹莓派上搭的博客地址:

http://www.codeforfun.info/

相關文章
相關標籤/搜索