go语言基础值传递
go语言中只有值传递,没有引用传递
值传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数,函数外和函数里对这个参数地址求值应该是不一样的。
引用传递是指在调用函数时将实际参数的地址直接传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。
值传递和引用传递的区别并不是传递的内容,而是实参到底有没有被复制一份给形参。 在判断实参内容有没有受影响的时候,要看传的是什么,如果你传递的是个地址,那么就看这个地址的变化会不会有影响,而不是看地址指向的对象的变化。
package main
import "fmt"
func main() {
slice := []int{0,1,2,3}
m := make(map[string]string)
m["A"] = "a"
var i *int
a := 123
i = &a
fmt.Printf("[main pointer] %p\n", &i)
fmt.Printf("[main map] %p\n", &m)
fmt.Printf("[main slice] %p\n", &slice)
get(slice, m, i)
fmt.Println(slice)
fmt.Println(m)
fmt.Println(*i)
}
func get(s []int, m map[string]string, i *int) {
fmt.Printf("[get pointer] %p\n", &i)
fmt.Printf("[get map] %p\n", &m)
fmt.Printf("[get slice] %p\n", &s)
s[1] = 9
m["A"] = "Hello"
a := 456
i = &a
}
运行结果如下:
[main pointer] 0xc00000e030
[main map] 0xc00000e028
[main slice] 0xc00000c030
[get pointer] 0xc00000e048
[get map] 0xc00000e040
[get slice] 0xc00000c048
[0 9 2 3]
map[A:Hello]
123
可以发现slice、map、指针在传递过程中地址都发生了变化,这说明传递的是一份拷贝。
但是我们又发现在函数里修改slice、map,函数外的值也会改变,这是为什么呢?
slice本身是个结构体,源码里的定义如下:
type slice struct {
array unsafe.Pointer
len int
cap int
}
slice底层是通过指针指向数组的,故函数内的切片跟函数外的切片访问的数组是同一个地址的,函数内修改切片也会影响到函数外的切片。
package main
import (
"fmt"
"log"
)
var str []string
func main() {
fmt.Printf("[main slice] %p\n", str)
fmt.Printf("[main slice] %p\n", &str)
str=[]string{"c"}
fmt.Printf("[main slice c] %p\n", str)
fmt.Printf("[main slice c] %p\n", &str)
setVal(&str)
log.Println(str)
}
func setVal(val *[]string) {
fmt.Printf("[val slice] %p\n", &val)
*val = []string{"a", "b"}
fmt.Printf("[val slice] %p\n", val)
}
运行结果如下:
[main slice] 0x0
[main slice] 0x113e0b0
[main slice c] 0xc000010230
[main slice c] 0x113e0b0
[val slice] 0xc00000e030
[val slice] 0x113e0b0
[a b]