一、今日题目:
-
下面选项正确的是:
A. 类型可以声明在函数体内;
B. Go语言支持 + + i 或者 - - i;
C .nil是关键字;
D. 匿名函数可以直接赋值给一个变量或者直接执行。 -
下面的代码会输出什么?
package main
import "fmt"
func main() {
f := F(5)
defer func() {
fmt.Println("defer1:",f())
}()
defer fmt.Println("defer2:",f())
i := f()
fmt.Println("i:",i)
}
func F(n int) func() int {
return func() int {
n++
return n
}
}
二、答案:
- AD
-
i: 7
defer2: 6
defer1: 8
三、解析
-
B. Go中++,- - 操作与C语言不一样。可以使用i++,i- -,但是++i,- - i是错误的。此外需要注意的是:i++和i- -在go语言中是语句,不是表达式,所以不能赋值给另外的变量,即:var a=i++ 是错误的。
C. nil是预定义的标识符,代表指针、通道、函数、接口、映射或切片的零值,也就是预定好的一个变量。并不是Go的关键字之一。 -
defer()后面的函数如果带参数,会优先计算参数,并将结果存储在栈中,到真正执行defer()的时候取出。
四、知识点:匿名函数,defer()
1. 匿名函数:
- 函数也是一种类型,因此可以定义作为一个函数类型的变量
- 匿名函数即没有名字的函数
- 闭包:一个函数和与其相关的引用环境组合组成的实体
2. defer():defer代码块会在函数调用链表中增加一个函数调用,会正常返回。也就是在return之后添加一个函数调用,也就是说:defer函数会在return之后被调用。因此,defer通常用来释放函数内部变量。
-
当defe被声明时,其参数就会被实时解析。
func a() { i := 0 defer fmt.Println(i) //输出0,因为i此时就是0 i++ defer fmt.Println(i) //输出1,因为i此时就是1 return }
输出结果:1,0
-
defer 执行顺序为先进后出
-
defer可以读取有名返回值
func c() (i int) { defer func() { i++ }() return 1 }
输出结果:1,2
解析:defer是在return调用之后才执行的。这里需要明确的是defer代码块的作用域仍然在函数之内,因此defer仍然可以读取c函数内的变量(如果无法读取函数内变量,那又如何进行变量清除呢…)
当return 1之后,i的值就是1。此时此刻,defer代码块开始执行,对i进行自增操作。 因此输出2.