GO切片傳值/引用/指標

weixin_41778945發表於2020-11-24

GO切片傳值/引用/指標

鄙人一直以為切片,map 在函式呼叫過程中傳遞是值傳遞。這一點沒錯。和大家想的一樣
但是此處有一個坑需要規避

就是 當所傳原切片長度變大後。就是增長後,Go底層會為其分配新的地址來儲存更多的值,這時候你傳的原切片地址就會變成新的。

原理:

append()新增資料時並不會影響實參(的長度)。 (可以通過返回值覆蓋(修改)實參的值(長度);或者通過切片的指標修改實參)

因此當函式中對原切片的長度進行擴增,呼叫append後,地址發生了變化。在不做返回值覆蓋的情況下,需要傳入原切片的指標。


package main
 
import "fmt"
 
// 值傳遞:改變形參的值,並不會改變實參的值。(例如:陣列、結構體)
// 地址傳遞(引用傳遞):改變形參的值,會影響到實參的值。(例如:切片、map、指標)(切片變數名本身就是一個地址)
 
// 陣列作為函式的引數,是值傳遞。 修改形參不會改變實參的值。(可以通過返回值來覆蓋(修改)實參的值)
// 切片的資料存放在記憶體的堆區。 陣列的資料(函式的區域性變數)存放在記憶體的棧區
 
func main() {
	// 定義切片。
	slice := []int{0, 1, 2, 3, 4}
	test(slice)
	fmt.Printf("%p \n", slice) // 0xc000072030
	fmt.Println(slice)   // [111 1 2 3 4]  (修改形參會影響到實參)
}
 
// 切片作為函式的引數(地址傳遞) (切片變數名本身就是一個地址)
func test(s []int) {
	fmt.Printf("%p \n", s) // 0xc000072030 與實參的地址相同
	s[0] = 111     // 修改形參會影響到實參
 
	***

//但是 append()新增資料時並不會影響實參(的長度)。 (可以通過返回值覆蓋(修改)實參的值(長度);或者通過切片的指標修改實參)***

	s = append(s, 66,77,88)
}

相關文章