这是我参与「第五届青训营 」伴学笔记创作活动的第 2 天
函数
为完成某一功能的程序指令(语句)的集合,称为函数。
在Go语言中,函数是第一类对象,我们可以将函数保持到变量中。函数主要有具名和匿名之分,包级函数一般都是具名函数,具名函数是匿名函数的一种特例,当匿名函数引用了外部作用域中的变量时就成了闭包函数,闭包函数是函数式编程语言的核心。
格式
func fuction_name([parameter list])[return types]{
函数体
}
具名函数
和c语言中的普通函数意义相同,具有函数名、返回值以及函数参数的函数。
func add(a, b int) int {
return a + b
}
匿名函数
指不需要定义函数名的一种函数实现方式,它由一个不带函数名的函数声明和函数体组成。
var Add = func(a, b int) int {
return a + b
}
fmt.Println(Add(1, 2))
名词解释
闭包函数:返回为函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域。
一级对象:支持闭包的多数语言都将函数作为第一级对象,就是说函数可以存储到变量中作为参数传递给其他函数,最重要的是能够被函数动态创建和返回。
包:go的每一个文件都是属于一个包的,也就是说go是以包的形式来管理文件和项目目录结构的。
函数传参
Go语言中的函数可以有多个参数和多个返回值,参数和返回值都是以传值的方式和被调用者交换数据。在语法上,函数还支持可变数量的参数,可变数量的参数必须是最后出现的参数,可变数量的参数其实是一个切片类型的参数。
func main() {
var a = []int{1, 2, 3}
Print("name", "wht")
Print(a)
}
func Print(a ...interface{}) {
fmt.Println(a...)
}
//name wht
//[1 2 3]
函数返回值
不仅函数的参数可以有名字,也可以给函数的返回值命名。
func swap(a, b int) (c, d int) {
c = b
d = a
return
}
func main() {
a, b := 1, 2
a, b = swap(a, b)
fmt.Println(a, b)
}
//2 1
defer
defer一般用于资源的释放和异常的捕捉, 作为Go语言的特性之一.
-
defer 语句会将其后面跟随的语句进行延迟处理. 意思就是说 跟在defer后面的语言 将会在程序进行最后的return之前再执行.
-
延迟函数的参数在defer语句出现时就已经确定了
-
在 defer 归属的函数即将返回时,将延迟处理的语句按 defer 的逆序进行执行,也就是说,先被 defer 的语句最后被执行,最后被 defer 的语句,最先被执行(defer进行压栈和弹栈过程)。
func main() { a := 1 defer fmt.Println(a) a = 2 defer fmt.Println(a) a = 3 defer fmt.Println(a) } //3 2 1 -
延迟函数可能操作主函数的具名返回值
当定义defer的函数(主函数)有返回值,返回值可能有名字(具名返回值),也可能没有名字(匿名返回值),延迟函数可能会影响返回值。
func deferFuncReturn() (result int) { i := 1 defer func() { result++ }() return i }//实际会解析成以下操作 result = i result ++ return函数返回过程:关键字return不是一个原子操作,实际上return只代表汇编指令ret,即跳转程序执行。
比如 return i ,实际上分两步执行,即先将 i 值存入栈中作为返回值,然后执行跳转,而defer的执行时机正是在跳转前,所以说defer执行时还是有机会操作返回值。