Go语言函数值传递和引用传递 图片看不了?点击切换HTTP 返回上层
Go语言默认使用按值传递来传递参数,也就是传递参数的副本。函数接收参数副本之后,在使用变量的过程中可能对副本的值进行更改,但不会影响到原来的变量,比如 Function(arg1) 。
如果你希望函数可以直接修改参数的值,而不是对参数的副本进行操作,你需要将参数的地址(变量名前面添加 & 符号,比如 &variable)传递给函数,这就是按引用传递,比如 Function(&arg1) ,此时传递给函数的是一个指针。
如果传递给函数的是一个指针,指针的值(一个地址)会被复制,但指针的值所指向的地址上的值不会被复制;我们可以通过这个指针的值来修改这个值所指向的地址上的值。指针也是变量类型,有自己的地址和值,通常指针的值指向一个变量的地址。所以,按引用传递也是按值传递。
几乎在任何情况下,传递指针(一个 32 位或者 64 位的值)的消耗都比传递副本来得少。在函数调用时,像切片(slice)、字典(map)、接口(interface)、通道(channel)这样的引用类型都是默认使用引用传递(即使没有显示的指出指针)。
有些函数只是完成一个任务,并没有返回值。我们仅仅是利用了这种函数的副作用,就像输出文本到终端,发送一个邮件或者是记录一个错误等。
但是绝大部分的函数还是带有返回值的。
下面的示例中 MultiPly3Nums 函数带有三个形参,分别是 a 、b 、c ,还有一个 int 类型的返回值(被注释的代码具有和未注释部分同样的功能,只是多引入了一个本地变量):
如果你希望函数可以直接修改参数的值,而不是对参数的副本进行操作,你需要将参数的地址(变量名前面添加 & 符号,比如 &variable)传递给函数,这就是按引用传递,比如 Function(&arg1) ,此时传递给函数的是一个指针。
如果传递给函数的是一个指针,指针的值(一个地址)会被复制,但指针的值所指向的地址上的值不会被复制;我们可以通过这个指针的值来修改这个值所指向的地址上的值。指针也是变量类型,有自己的地址和值,通常指针的值指向一个变量的地址。所以,按引用传递也是按值传递。
几乎在任何情况下,传递指针(一个 32 位或者 64 位的值)的消耗都比传递副本来得少。在函数调用时,像切片(slice)、字典(map)、接口(interface)、通道(channel)这样的引用类型都是默认使用引用传递(即使没有显示的指出指针)。
有些函数只是完成一个任务,并没有返回值。我们仅仅是利用了这种函数的副作用,就像输出文本到终端,发送一个邮件或者是记录一个错误等。
但是绝大部分的函数还是带有返回值的。
下面的示例中 MultiPly3Nums 函数带有三个形参,分别是 a 、b 、c ,还有一个 int 类型的返回值(被注释的代码具有和未注释部分同样的功能,只是多引入了一个本地变量):
package main import "fmt" func main() { fmt.Printf("Multiply 2 * 5 * 6 = %d\n", MultiPly3Nums(2, 5, 6)) // var i1 int = MultiPly3Nums(2, 5, 6) // fmt.Printf("MultiPly 2 * 5 * 6 = %d\n", i1) } func MultiPly3Nums(a int, b int, c int) int { // var product int = a * b * c // return product return a * b * c }输出显示:
Multiply 2 * 5 * 6 = 60
如果一个函数需要返回四到五个值,我们可以传递一个切片给函数(如果返回值具有相同类型)或者是传递一个结构体(如果返回值具有不同的类型)。因为传递一个指针允许直接修改变量的值,消耗也更少。