1. 程式人生 > >Go語言中切片作為函式引數,函式中使用append新增元素

Go語言中切片作為函式引數,函式中使用append新增元素

切片作為函式,通過append新增元素,有可能會更改地址:
1)新增的資料元素長度超過切片引數的容量,則會另開闢空間,重新分配底層陣列,並複製資料。函式中的此切片與原切片地          址不同; 此切片指向新開闢的記憶體。函式執行結束,記憶體釋放,不會影響元切片的內容。
2)否則原切片與函式中的切片指向同一地址。會影響切片的內容。

3)切片名本身就是一個指標(內容儲存指向切片的首地址)

程式碼測試:

package main
import "fmt"
func main01() {
	s := make([]int, 3, 5)
	s[2] = 8888
	fmt.Printf("原地址:%p", s)
	s = append(s, 12)
	fmt.Printf("\n新增資料之後的地址:%p", s)
	/*
	append新增元素,容量足夠,則在原基礎之上新增資料,地址不會發生改變
	輸出:
	原地址:0xc04207e030
	新增資料之後的地址:0xc04207e030
	*/
}
func main02() {
	s := make([]int, 3)
	s[2] = 666
	fmt.Printf("append新增資料之前的地址:%p", s)
	s = append(s, 888)
	fmt.Printf("\nappend新增資料之後的地址:%p", s)

	/*
	append新增資料,容量不夠,則另行開闢空間,切片地址發生變化
	輸出:
	append新增資料之前的地址:0xc04200e2c0
	append新增資料之後的地址:0xc04200a2d0
	*/
}
func main() {
	/*
	copy(目的切片,原切片):切片拷貝
	注意事項:目的切片要有足夠的空間,如果沒有空間(切片為空或者指向0x0),不能進行拷貝
	          若目的切片容量不足,只拷貝部分(目的切片長度的部分)
	返回值為拷貝成功的切片數量
	*/
	s := make([]int, 3)
	s[0] = 0
	s[1] = 111
	s[2] = 666
	//var s1 []int = []int{5: 333}
	//n:=copy(s,s1)
	s1 := make([]int, 1, 2)
	n := copy(s1, s)

	fmt.Printf("原切片s的地址是:%p", s)
	fmt.Printf("\n拷貝之後的切片s1的地址是:%p,數量:%d", s1, n)
	fmt.Println(s1)
}

補充說明:

陣列和slice之間有著緊密的聯絡。一個slice是一個輕量級的資料結構,提供了訪問陣列子序列(或者全部)元素的功能,而且slice的底層確實引用一個數組物件。一個slice由三個部分構成:指標、長度和容量。指標指向第一個slice元素對應的底層陣列元素的地址,要注意的是slice的第一個元素並不一定就是陣列的第一個元素。

切片並不是陣列或陣列指標,它通過內部指標和相關屬性引陣列段,以實現變⻓⽅案。

slice並不是真正意義上的動態陣列,而是一個引用型別。slice總是指向一個底層array,slice的宣告也可以像array一樣,只是不需要長度。