开发者学堂课程【Go 语言核心编程 - 基础语法、数组、切片、Map :函数参数的传递方式】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/625/detail/9612
函数参数的传递方式
基本内容
一、 基本介绍
二、 两种传递方式
三、 值类型和引用类型
四、 值传递和引用传递使用特点
一、基本介绍
函数注意事项和使用细节中,讲了值类型和引用类型了,这个是重难点,再系统总结一下,在开发的时候会经常用到这个知识点,值类型参数默认就是值传递,而引用类型参数默认就是引用传递。
二、两种传递方式
1、 值传递
比如说之前的基本数据类型就是值传递,所谓值传递就是在传递参数的时候进行了一个子拷贝,这个就是值传递。
2、 引用传递
引用传递就是一个地址。其实,值传递和引用传递的本质是一样的。不管是值传递还是引用传递,传递给函数的都是变量的副本。不同的是:
值传递的是值的拷贝(比如说传了一个整数6,传过去给函数之后,函数会得到一个新的6,是一个值)。
引用传递的是地址的拷贝(比如说指针,如果希望函数内的变量能够修改函数外的变量就可以用引用传递,使用指针传递其实就是引用传递)。
一般来说,地址拷贝效率高。因为数据量小,而值拷贝决定拷贝的数据大小,数据越大,效率越低。
在 test03 之中传了个地址过去,传了地址给指针,指针其实是引用传递类型,指针在传地址的时候也进行了一个拷贝,也传递了一个具体的值,只是这个值不是20具体的数据内容,而是一个地址。
// n1就是*int 类型
func teste3(n1 *int) {
*n1 = *n1 + 10
fmt.Println( "teste3()n1= ", *n1) // 30
}
func main() {
//num := 20
//teste2(num)
//fmt.Println("main() num= ", num)
num := 20
teste3(&num)
fmt.Println( "main() num= ", num)// 30
}
假设 num 是一个数,拷贝一个数过去和拷贝一个地址过去效率肯定不一样,地址数据量比较小,很快就能传过去,结构体的内容量很大,结构体默认也是子拷贝,用子拷贝过去,就会产生一个很大的数,效率就比较低,如果传递的是一个结构体的地址,效率就会高。
三、值类型和引用类型
1、 值类型: 基本数据类型 int 系列, float 系列, bool, string 、数组和结构体 struct。
2、 引用类型: 指针、slice 切片、map、管道 chan、interface 等都是引用类型。
3、 暂时引用传递就讲了一个指针,需要非常清楚的认识哪些是值传递哪些是引用传递,这样在做开发的时候效率更高。
四、值传递和引用传递使用特点
在讲变量的时候讲了值传递和引用传递的类型,在此继续回顾一下,这个知识点非常重要。
1、 值类型默认是值传递,变量直接存储值,内存通常在栈中分配
【案例:画出示意图】
num=100,num 直接和这个值放到一起,如果 num 取地址,这个地址就是值所对应的地址。
2、 引用类型默认是引用传递,变量存储的是一个地址,这个地址对应的空间才真正存储数据(值),内存通常在堆上分配,当没有任何变量引用这个地址时,该地址对应的数据空间就成为一个垃圾,由 GC 来回收。
【案例,并画出示意图】
有个引用类型 ref ,并没有直接指向这个值,它是先指向一个地址,这个地址再指向这个值,这是引用传递的一个特点。
3、 如果希望函数内的变量能修改函数外的变量,可以传入变量的地址&,函数内以指针的方式操作变量。从效果上看类似引用。在详解函数使用的注意事项的第6点讲过。