function and defer in GO
1、GO语言中函数可以有多返回值
func operate(num1 int,num2 int)(difference int,plus int) {
difference=num1-num2
plus=num1+num2
return difference,plus
}
a,b:=16,14
c,d:=operate(a,b)
fmt.Println("a与b的差为",c,"\na与b的和为",d)
输出:
a与b的差为 2
a与b的和为 30
比较常用的是foreach时第一个返回值为index,第二个返回值为value以及判断map的key是空值还是零值和判断是否发生error等等,不一一列举了
2、函数式编程(装饰器)
代码实现一个计算函数运行时间的装饰器
func time_Spent(inner func(int)int)func(int)int{
return func(i int) int {
startTime:=time.Now()
ret:=inner(i)
fmt.Printf("function spent time:%f s",time.Since(startTime).Seconds()-1)//在计算时间的函数里sleep一秒
return ret//这里是把inner的返回值赋给ret然后调用装饰后的函数的时候返回ret,也就实现了原函数的返回值的返回
}
func Factorial(num int) int {
time.Sleep(time.Second*1)
result:=num
for i:=num;i>0;i--{
result*=i
}
return result
}
fmt.Printf("\n %v的阶乘为%v",a,time_Spent(Factorial)(a))
输出:
function spent time:0.000752 s
16的阶乘为3347646382080005
3、defer[dɪ’fɜr]
defer,意为推迟,推迟调用匿名或非匿名函数,多个defer从下向上执行,可以用来执行收尾工作,无知的我一开始读作['defɜr],这玩意很好玩,我们来看看
func Add(args...int)int {//这里用了一个可变长参数,及任意数量的int类型生成一个数组
result := 0
for _, arg := range args {
result += arg
fmt.Println(result)
}
defer func(i int){
fmt.Println("\nnow ,result is",i)
}(result)
return result
}
fmt.Println("\n",Add(5,9,8,7,56,4,))
这时候输出:
14
22
29
85
89
now ,result is 89
89
我们换一下defer在函数中的位置:
func Add(args...int)int {
result := 0
defer func(i int){
fmt.Println("\nnow ,result is",i)
}(result)
for _, arg := range args {
result += arg
fmt.Println(result)
}
return result
}
输出:
14
22
29
85
89
now ,result is 0
89
不难看出这个东西是运行到他,保存他的状态,之后函数该怎么运行怎么运行,在关闭函数之前将他唤醒,依照原状态运行。
defer的小坑
defer对于匿名返回值与非匿名返回值的影响不同
func do(arg int)(res int){
res=1000
defer func() {res=10}()
return res
}
fmt.Println(do(1000))
函数非匿名返回值时:
10
func do(arg int)(int){
res:=1000
defer func() {res=10}()
return res
}
fmt.Println(do(1000))
匿名时呢:
1000
之所以会这样,原因很明了,因为非匿名时执行defer会改变作为返回值的res但是匿名时res的值在defer执行之前已经赋给了返回的变量(我们不知道这个变量是什么,在非匿名时他就是res,匿名时则不同,但他就是关闭函数时返回的值的由来)所以这时通过defer改变函数体里的res的值已经对返回值没有影响了。