1. 程式人生 > >go語言切片作為函數參數的研究

go語言切片作為函數參數的研究

修改 結果 main 長度 () port 切片slice cap lan

slice作為函數參數是值傳遞

golang中的切片slice底層通過數組實現,slice類似一個結構體,其中一個字段保存的是底層數組的地址,還有長度(len) 和 容量(cap)兩個字段。

結構體作為函數參數時是值拷貝,同理,實際上slice作為函數參數時也是值拷貝,在函數中對slice的修改是通過slice中保存的地址對底層數組進行修改,所以函數外的silce看起來被改變了。

當需要對slice做插入和刪除時,由於需要更改長度字段,值拷貝就不行了,需要傳slice本身在內存中的地址。

以刪除為例,說明這種情況。

不通過函數,直接刪除slice中的一個元素

package main

import "fmt"

func main() {
    si := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}

    fmt.Printf("%v  len %d \n", si, len(si))
    
    si = append(si[:3],si[4:]...)
    
    fmt.Printf("%v  len %d \n", si, len(si))
}
// ---------輸出結果-------------------
[1 2 3 4 5 6 7 8 9]  len 9 
[1 2 3 5 6 7 8 9]  len 8 
// --------成功刪除了4  長度減1---------

通過函數,參數是slice變量

func main() {
    si := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}

    fmt.Printf("%v  len %d \n", si, len(si))
    
    test1(si)
    
    fmt.Printf("%v  len %d \n", si, len(si))
}

func test1(si []int) {
    si = append(si[:3], si[4:]...)
}

// -------------輸出結果-------------------
[1 2 3 4 5 6 7 8 9]  len 9 
[1 2 3 5 6 7 8 9 9]  len 9 
// -----4雖然被刪除了,但是長度不變,最後面還多了個9,可見不是想要的結果

通過函數,參數是slice變量的地址

func main() {
    si := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}

    fmt.Printf("%v  len %d \n", si, len(si))
    
    test(&si)

    fmt.Printf("%v  len %d \n", si, len(si))
}

func test(si *[]int) {
    (*si) = append((*si)[:3], (*si)[4:]...)
}


// ---------輸出結果-------------------
[1 2 3 4 5 6 7 8 9]  len 9 
[1 2 3 5 6 7 8 9]  len 8 
// --------成功刪除了4  長度減1---------

go語言切片作為函數參數的研究