go中预定义引用类型:slice、map、channel
函数传递map
func main() {
m := make(map[string]int)
m["aaa"]=100
m["bbb"]=200
fmt.Printf("pointer: %p, target: %v\n",&m,m)
testTransfer3(m)
fmt.Printf("pointer: %p, target: %v\n",&m,m)
}
func testTransfer3(m map[string]int){
fmt.Printf("pointer: %p, target: %v\n",&m,m)
m["aaa"]=1
}
输出:
pointer: 0xc00008a018, target: map[aaa:100 bbb:200]
pointer: 0xc00008a028, target: map[aaa:100 bbb:200]
pointer: 0xc00008a018, target: map[aaa:1 bbb:200]
引用类型,传参时是【指针拷贝传递】,拷贝的是【指针】。即方法内的变量与方法外的变量地址不同(拷贝时新创建变量),但是指向相同(拷贝出来的指针与原指针指向相同)。
函数传递slice
例一
func main() {
var slice1=[]int {1,2,3}
fmt.Printf("pointer: %p, target: %v\n",&slice1,slice1)
testTransfer3(slice1)
fmt.Printf("pointer: %p, target: %v\n",&slice1,slice1)
}
func testTransfer3(slice []int){
fmt.Printf("pointer: %p, target: %v\n",&slice,slice)
slice[0] = 0
}
输出:
pointer: 0xc0000044c0, target: [1 2 3]
pointer: 0xc000004520, target: [1 2 3]
pointer: 0xc0000044c0, target: [0 2 3]
引用类型,传参时是【指针拷贝传递】,拷贝的是【指针】。即方法内的变量与方法外的变量地址不同(拷贝时新创建变量),但是指向相同(拷贝出来的指针与原指针指向相同)。改变的是指针指向的切片内容,所以所有指向该切片的指针都受影响。
例二
func main() {
var slice1=[]int {1,2,3}
fmt.Printf("pointer: %p, target: %v\n",&slice1,slice1)
testTransfer3(slice1)
fmt.Printf("pointer: %p, target: %v\n",&slice1,slice1)
}
func testTransfer3(slice []int){
fmt.Printf("pointer: %p, target: %v\n",&slice,slice)
slice = append(slice, 4,5)
}
输出:
pointer: 0xc0000044c0, target: [1 2 3]
pointer: 0xc000004520, target: [1 2 3]
pointer: 0xc0000044c0, target: [1 2 3]
引用类型,传参时是【指针拷贝传递】,拷贝的是【指针】。即方法内的变量与方法外的变量地址不同(拷贝时新创建变量),但是指向相同(拷贝出来的指针与原指针指向相同)。方法内改变了slice1的指向,方法外的slice1指向未改变。
例三
func main() {
var slice1 = make([]int,3,10)
slice1[0] = 1
slice1[1] = 2
slice1[2] = 3
fmt.Printf("pointer: %p, target: %v,%v,%v\n",&slice1,slice1,len(slice1),cap(slice1))
testTransfer3(slice1)
fmt.Printf("pointer: %p, target: %v,%v,%v\n",&slice1,slice1,len(slice1),cap(slice1))
}
func testTransfer3(slice []int){
fmt.Printf("pointer: %p, target: %v,%v,%v\n",&slice,slice,len(slice),cap(slice))
slice = append(slice, 4,5)
}
输出:
pointer: 0xc0000044c0, target: [1 2 3],3,10
pointer: 0xc000004520, target: [1 2 3],3,10
pointer: 0xc0000044c0, target: [1 2 3],3,10
引用类型,传参时是【指针拷贝传递】,拷贝的是【指针】。即方法内的变量与方法外的变量地址不同(拷贝时新创建变量),但是指向相同(拷贝出来的指针与原指针指向相同)。方法内改变了slice1的指向,方法外的slice1指向未改变。
例四
func main() {
var slice1=[]int {1,2,3}
fmt.Printf("pointer: %p, target: %v\n",&slice1,slice1)
testTransfer3(&slice1)
fmt.Printf("pointer: %p, target: %v\n",&slice1,slice1)
}
func testTransfer3(slice *[]int){
fmt.Printf("pointer: %p, target: %v\n",slice,*slice)
*slice = append(*slice, 4,5)
}
输出:
pointer: 0xc0000044c0, target: [1 2 3]
pointer: 0xc0000044c0, target: [1 2 3]
pointer: 0xc0000044c0, target: [1 2 3 4 5]
值类型,传参时是【值拷贝传递】,拷贝的是【值(slice1的地址)】。方法内改变了指针指向的内容,方法外的slice1与方法内为同一指针,内容也改变。不管是指针、引用类型,还是其他类型参数,都是值拷贝传递,区别无非是拷贝目标对象,还是拷贝指针而已。在函数调用前,会为形参和返回值分配内存空间,并将实参拷贝到形参内存。
版权声明:本文为libie_lt原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。