内容简介:Go 默认使用按值传递来传递参数,也就是传递参数的副本。函数接收参数副本之后,在使用变量的过程中可能对副本的值进行更改,但不会影响到原来的变量,比如 Function(arg1)。如果你希望函数可以直接修改参数的值,而不是对参数的副本进行操作,你需要将参数的地址(变量名前面添加&符号,比如 &variable)传递给函数,这就是按引用传递,比如 Function(&arg1),此时传递给函数的是一个指针。如果传递给函数的是一个指针,指针的值(一个地址)会被复制,但指针的值所指向的地址上的值不会被复制;我们
按值传递和按引用传递
Go 默认使用按值传递来传递参数,也就是传递参数的副本。函数接收参数副本之后,在使用变量的过程中可能对副本的值进行更改,但不会影响到原来的变量,比如 Function(arg1)。
如果你希望函数可以直接修改参数的值,而不是对参数的副本进行操作,你需要将参数的地址(变量名前面添加&符号,比如 &variable)传递给函数,这就是按引用传递,比如 Function(&arg1),此时传递给函数的是一个指针。如果传递给函数的是一个指针,指针的值(一个地址)会被复制,但指针的值所指向的地址上的值不会被复制;我们可以通过这个指针的值来修改这个值所指向的地址上的值。(译者注:指针也是变量类型,有自己的地址和值,通常指针的值指向一个变量的地址。所以,按引用传递也是按值传递。)
几乎在任何情况下,传递指针(一个32位或者64位的值)的消耗都比传递副本来得少。
在函数调用时,像切片(slice)、字典(map)、接口(interface)、通道(channel)这样的引用类型都是默认使用引用传递(即使没有显式的指出指针)。
传递变长参数
如果函数的最后一个参数是采用 ...type 的形式,那么这个函数就可以处理一个变长的参数,这个长度可以为 0,这样的函数称为变参函数。
func myFunc(a, b, arg ...int) {}
这个函数接受一个类似某个类型的 slice 的参数 ,该参数可以通过for 循环结构迭代。
示例函数和调用:
func Greeting(prefix string, who ...string) Greeting("hello:", "Joe", "Anna", "Eileen")
在 Greeting 函数中,变量 who 的值为 []string{"Joe", "Anna", "Eileen"}。
如果参数被存储在一个数组 arr 中,则可以通过 arr... 的形式来传递参数调用变参函数。
defer 和追踪
关键字 defer 允许我们推迟到函数返回之后(或任意位置执行 return 语句之后)一刻才执行某个语句或函数(为什么要在返回之后才执行这些语句?因为 return 语句同样可以包含一些操作,而不是单纯地返回某个值)。关键字 defer 的用法类似于面向对象编程语言 Java 和 C# 的 finally 语句块,它一般用于释放某些已分配的资源。
package main
import"fmt"
func main(){
function1()
}
func function1(){
fmt.Printf("In function1 at the top\n")
defer function2()
fmt.Printf("In function1 at the bottom!\n")
}
func function2(){
fmt.Printf("function2: Deferred until the end of the calling function!")
}
输出:
In Function1 at the topIn Function1 at the bottom!
Function2: Deferred until the end of the calling function!
当有多个 defer 行为被注册时,它们会以逆序执行(类似栈,即后进先出):
func f(){
for i :=0; i <5; i++ {
defer fmt.Printf("%d ", i)
} }
上面的代码将会输出:4 3 2 1 0。
将函数作为参数
package main
import("fmt")
func main()
{ callback(1, Add) }
func Add(a, b int){
fmt.Printf("The sum of %d and %d is: %d\n", a, b, a+b)}
func callback(yint, f func(int,int)){
f(y,2)// this becomes Add(1, 2)
}
闭包
当我们不希望给函数起名字的时候,可以使用匿名函数,例如:func(x, y int) int { return x + y }。
这样的一个函数不能够独立存在(编译器会返回错误:non-declaration statement outside function body),但可以被赋值于某个变量,即保存函数的地址到变量中:fplus := func(x, y int) int { return x + y },然后通过变量名对函数进行调用:fplus(3,4)。
当然,也可以直接对匿名函数进行调用:func(x, y int) int { return x + y } (3, 4)。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- Python 函数调用&定义函数&函数参数
- php梳理-函数[参数]
- Python 函数参数的拆解
- 如何减少函数参数的输入
- python中函数的参数传递
- Shell编程—【04】函数的定义、参数、变量作用域、函数库
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
高效能程序员的修炼
[美]Jeff Atwood / 陆其明、张健 / 人民邮电出版社 / 2013-7 / 49
jeff atwood于2004年创办coding horror博客(http://www.codinghorror.com),记录其在软件开发经历中的所思所想、点点滴滴。时至今日,该博客每天都有近10万人次的访问量,读者纷纷参与评论,各种观点与智慧在那里不断激情碰撞。 《高效能程序员的修炼》是coding horror博客中精华文章的集合。全书分为12章,涉及迈入职业门槛、高效能编程、应聘......一起来看看 《高效能程序员的修炼》 这本书的介绍吧!