golang 中引用类型有:slice、map、interface、channel
golang所有类型在函数中都是值传递,这个跟上面golang中有的数据类型为引用类型并不冲突,用下面四个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)
}
// 输出结果
// 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 函数中slice[0]说明 fn 函数里面的修改,也改变函数外的值,这跟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)
}
// 输出结果
// 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导致空间不足,分配新地址,fn外地址不变,导致append的值函数外获取不到??那就分配足够的空间见例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)
}
// 输出结果
// 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 分配了足够的空间发现,fn内部append依旧没有生效,观察地址发现fn内部的地址和函数外的地址不一致,因为fn方法参数为切片,而不是切片数组,slice 底层结构为len、cap和指向存储位置的地址,slice 在函数间传递,指向存储位置的地址的指针是一致,但是不同函数的slice不是同一个对下个,对应的len、cap是不一致的文章来源:https://www.toymoban.com/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)
}
// 输出结果
// 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]
说明:函数间的参数传递改为指针,保证函数内外完全是同一个值,故函数内的修改和append函数外都能获取到文章来源地址https://www.toymoban.com/news/detail-613472.html
到了这里,关于golang slice 作为参数值传递情况说明的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!