实参与形参数
func printNumber(args ...int)
- 形式参数:是在定义函数名和函数体的时候使用的参数,目的是用来接收调用该函数时传入的参数。
- 实际参数:在调用有参函数时,主调函数和被调函数之间有数据传递关系。在主调函数中调用一个函数时,函数名后面括号中的参数称为“实际参数”。
func main() { var args int64= 1 printNumber(args) // args就是实际参数 } func printNumber(args ...int64) { //这里定义的args就是形式参数 for _,arg := range args{ fmt.Println(arg) } }
什么是值传递
什么是值传递,传递的是值,也就是说,函数传递的原来数据的拷贝,一个副本,比如当传递一个 int 类型的参数,传递的其实是这个参数的一个副本。传递一个指针类型的参数,其实传递的就是这个指针类型的拷贝,而不是这个指针执行的值。
什么是引用传递
引用传递是指在函数调用过程中,是将实际参数的地址传递到函数中, 然后在函数中对参数进行修改,会影响到实际值。
golang是值传递
package gobase import ( "fmt" "testing" ) func TestReference(t *testing.T) { var args int64 = 1 modifiedNumber(args) // args就是实际参数 fmt.Printf("实际参数的地址 %p\n", &args) fmt.Printf("改动后的值是 %d\n", args) } func modifiedNumber(args int64) { //这里定义的args就是形式参数 fmt.Printf("形参地址 %p \n", &args) args = 10 }
运行结果:
=== RUN TestReference 形参地址 0xc0000a01c8 实际参数的地址 0xc0000a01c0 改动后的值是 1 --- PASS: TestReference (0.00s) PASS
上面运行结果可以看出,go 是值传递, 但是不能确定 Go 是否只有值传递,也没有引用传递?
传递一个引用参数类型测试一下:
func TestReference2(t *testing.T) { var args int64= 1 addr := &args fmt.Printf("原始指针的内存地址是 %p\n", addr) fmt.Printf("指针变量addr存放的地址 %p\n", &addr) modifiedNumber2(addr) // args就是实际参数 fmt.Printf("改动后的值是 %d\n",args) } func modifiedNumber2(addr *int64) { //这里定义的args就是形式参数 fmt.Printf("形参地址 %p \n",&addr) *addr = 10 }
运行结果
=== RUN TestReference2 原始指针的内存地址是 0xc0001221d0 指针变量addr存放的地址 0xc00012c028 形参地址 0xc00012c030 改动后的值是 10 --- PASS: TestReference2 (0.00s) PASS
通过输出可以看到,这个是指针拷贝, 存放两个指针到地址是不一样的, 虽然指针的内容相同,但是两个是不一样的指针。
我们声明了一个变量 args , 其值为1, 内存存放地址为 0xc000b4008 , 通过这个地址可以找到变量 args, 这个地址是 args 的指针 addr, 指针adrr其实也是一个指针类型的变量。需要内存来存放它, 对应的内存地址是 0xc000ae18, 指针存放的内容是 0xc000b4008, 在我们传递指针变量 addr 给 modifedNumber 的时候,该指针变量是指针的一个拷贝, 新拷贝的指针变量存放地址是 0xc0000ae028 ,对应存放的内容还是 0xc000b4008, 这个指向了 args 变量的, 于是可以修改 0xc000b4008 指针对应的值,也就是修改了 args 对应的值。