golang 中引用類型有:slice、map、interface、channel
golang所有類型在函數(shù)中都是值傳遞,這個跟上面golang中有的數(shù)據(jù)類型為引用類型并不沖突,用下面四個slice實例幫助理解
// 例子 1
func fn(s []int) {
s[0] = 3
}
func main() {
slice := []int{1,2}
fmt.Printf("before fn slice len:%d, cap:%d, add:%p", len(slice), cap(slice), slice)
fmt.Println("before fn slice data:",slice)
fn(slice)
fmt.Printf("after fn slice len:%d, cap:%d, add:%p", len(slice), cap(slice), slice)
fmt.Println("after fn slice data:",slice)
}
// 輸出結(jié)果
// before fn slice len:2, cap:2, add:0xc000132b00before fn slice data: [1 2]
// after fn slice len:2, cap:2, add:0xc000132b00after fn slice data: [3 2]
說明: main 函數(shù)中slice[0]說明 fn 函數(shù)里面的修改,也改變函數(shù)外的值,這跟slice為引用類型的緣故
// 例子 2
func fn(s []int) {
s[0] = 3
s = append(s, 4)
fmt.Printf("fn in slice len:%d, cap:%d, add:%p", len(s), cap(s), s)
fmt.Println("fn in slice data:", s)
}
func main() {
slice := []int{1,2}
fmt.Printf("before fn slice len:%d, cap:%d, add:%p", len(slice), cap(slice), slice)
fmt.Println("before fn slice data:",slice)
fn(slice)
fmt.Printf("after fn slice len:%d, cap:%d, add:%p", len(slice), cap(slice), slice)
fmt.Println("after fn slice data:",slice)
}
// 輸出結(jié)果
// before fn slice len:2, cap:2, add:0xc000026ba0before fn slice data: [1 2]
// fn in slice len:3, cap:4, add:0xc0000244c0fn in slice data: [3 2 4]
// after fn slice len:2, cap:2, add:0xc000026ba0after fn slice data: [3 2]
說明:slice[0] 被修改原因見例1,fn中append的值沒有帶出來,這里是slice原始分配的空間為2,append導(dǎo)致空間不足,分配新地址,fn外地址不變,導(dǎo)致append的值函數(shù)外獲取不到??那就分配足夠的空間見例3
// 例子 3
func fn(s []int) {
s[0] = 3
s = append(s, 4)
fmt.Printf("fn in slice len:%d, cap:%d, add:%p", len(s), cap(s), s)
fmt.Println("fn in slice data:", s)
}
func main() {
slice := make([]int, 0, 4)
// slice = []int{1,2} // 直接賦值會修改slice的地址
slice = append(slice,1,2)
fmt.Printf("before fn slice len:%d, cap:%d, add:%p", len(slice), cap(slice), slice)
fmt.Println("before fn slice data:",slice)
fn(slice)
fmt.Printf("after fn slice len:%d, cap:%d, add:%p", len(slice), cap(slice), slice)
fmt.Println("after fn slice data:",slice)
}
// 輸出結(jié)果
// before fn slice len:2, cap:2, add:0xc000026ba0before fn slice data: [1 2]
// fn in slice len:3, cap:4, add:0xc0000244c0fn in slice data: [3 2 4]
// after fn slice len:2, cap:2, add:0xc000026ba0after fn slice data: [3 2]
說明:slice 分配了足夠的空間發(fā)現(xiàn),fn內(nèi)部append依舊沒有生效,觀察地址發(fā)現(xiàn)fn內(nèi)部的地址和函數(shù)外的地址不一致,因為fn方法參數(shù)為切片,而不是切片數(shù)組,slice 底層結(jié)構(gòu)為len、cap和指向存儲位置的地址,slice 在函數(shù)間傳遞,指向存儲位置的地址的指針是一致,但是不同函數(shù)的slice不是同一個對下個,對應(yīng)的len、cap是不一致的文章來源:http://www.zghlxwxcb.cn/news/detail-613472.html
// 例子 4
func fn(s *[]int) {
(*s)[0] = 3
*s = append(*s, 4)
}
func main() {
slice := make([]int, 0, 4)
// slice = []int{1,2} // 直接賦值會修改slice的地址
slice = append(slice,1,2)
fmt.Printf("before fn slice len:%d, cap:%d, add:%p", len(slice), cap(slice), slice)
fmt.Println("before fn slice data:",slice)
fn(&slice)
fmt.Printf("after fn slice len:%d, cap:%d, add:%p", len(slice), cap(slice), slice)
fmt.Println("after fn slice data:",slice)
}
// 輸出結(jié)果
// before fn slice len:2, cap:2, add:0xc000026b80before fn slice data: [1 2]
// after fn slice len:3, cap:4, add:0xc0000244a0after fn slice data: [3 2 4]
說明:函數(shù)間的參數(shù)傳遞改為指針,保證函數(shù)內(nèi)外完全是同一個值,故函數(shù)內(nèi)的修改和append函數(shù)外都能獲取到文章來源地址http://www.zghlxwxcb.cn/news/detail-613472.html
到了這里,關(guān)于golang slice 作為參數(shù)值傳遞情況說明的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!