Go切片作為函式引數時的一些思考

2022-10-11 00:18:22 字數 1796 閱讀 6120

go語言中的切片事實上就是是乙個結構體,其執行時結構如下:

type slice struct
這一點非常重要,這也就意味著,將切片作為函式引數時,其傳遞機制與結構體傳遞機制一樣,都是值傳遞,也即傳遞的是原切片的拷貝。

另外乙個非常重要的點就是,切片結構體中的array是乙個指標,意味著array的值是底層陣列的位址,通過函式傳參後,這個值依然沒有改變。

因此可以看到,當把切片作為函式引數傳遞時,在函式中對切片進行某些修改操作,會影響到函式外的原始切片。

先看一段**:

func main() 

fmt.printf("arr pointer: %p\n", &arr)

test(arr)

fmt.printf("arr: %v\n", arr)

}func test(data int)

問題:

請問上述**中arr pointer:data pointer:的輸出是相同的嗎?

請問上述**中arr:列印的結果是多少?也即函式中對切片的修改會不會影響到函式外的原切片?

答案:輸出中arr pointer:data pointer:的值不相同,這很好理解,這是因為切片是值傳遞,傳遞給函式的時候,重新建立了乙個新的切片結構體,那麼二者的位址當然不一樣了。

列印的結果是arr: [100 2 3 4 5],也就證明了對切片的修改會影響到原切片。也正是這個原因導致很多人誤以為切片作為函式引數時是引用傳遞,其實這種理解是錯誤的。

func main() 

fmt.printf("arr pointer: %p\n", &arr)

test(arr)

fmt.printf("arr: %v\n", arr)

}func test(data int)

那麼問題來了:

此時arr:列印的結果是什麼?

最後,我想說的是,如果你確定編寫的函式需要將切片的修改影響到函式外的原始切片,那麼你的函式引數應該使用指標。

希望現在你可以清楚地回答下面的問題了

// **一

func main()

fmt.printf("arr pointer: %p\n", &arr)

test(&arr)

fmt.printf("arr: %v\n", arr)

}func test(data *int)

// **二

func main()

fmt.printf("arr pointer: %p\n", &arr)

test(&arr)

fmt.printf("arr: %v\n", arr)

}func test(data *int)

問題:

請問上述**中arr pointer:data pointer:的輸出是相同的嗎?

請問上述**中arr:列印的結果是多少?

附屬小問題:

var arr = int

fmt.printf("arr pointer: %p\n", arr)

fmt.printf("arr pointer: %p\n", &arr)

上面
Go 陣列 切片作為函式的引數。值傳遞 引用傳遞

demo.go 切片 陣列作為函式的形參 package main import fmt 值傳遞 改變形參的值,並不會改變實參的值。例如 陣列 結構體 陣列作為函式的引數,是值傳遞。修改形參不會改變實參的值。可以通過返回值來覆蓋 修改 實參的值 切片的資料存放在記憶體的堆區。陣列的資料 函式的區域性...

C 中陣列以及多維陣列作為函式引數時的一些問題

output1 ia,sizeof ia sizeof ia 0 今天在做 c primer 上的習題的時候,遇到了乙個小問題。原始函式如下 void output1 int a cout endl 陣列a為一維整型陣列,利用函式實現元素的依次輸出。但是編譯器在for int i a 處提示錯誤,i...

Redis作為快取時的一些使用經驗

redis作為nosql資料庫,經常用作快取,所以推薦將那些經常查詢的資料存入redis中方便下次快速獲取。但redis沒有像關係型資料庫那樣擁有結構化的查詢語言,如果快取了很多資料,想從中獲取滿足某些條件的資料時,該如何做呢?如果把這些海量資料從redis裡拿出來,逐個遍歷篩選出滿足條件的資料,這...