golang基础笔记(5):函数
函数
Go语言中支持函数、匿名函数和闭包。
函数在Go语言中可以作为变量、参数、返回值等等。
定义
1 | func 函数名([参数列表]) [返回值列表] { |
返回值
一个函数可以有0个或者多个返回值
1 | //简单的函数 |
在调用有返回值的函数时,我们可以选择不接受它的返回值。
当我们一个函数返回值为silce时,nil可以看做是一个silce,直接返回nil即可,不需要返回一个[]int{}
1 | func nilFunc() []int{ |
参数
可变参数
可变参数是指函数的参数数量不固定。Go语言中的可变参数通过在参数类型前加...
来标识。
注意:可变参数一般放在函数参数最后面。
1 | func main() { |
从输出的结果可以看出,可变参数x在函数体内被是视作一个int类型的切片;
但是在函数体外,可变参数不能被视作一个切片
1 | func f1(...int){} |
可以看出,两种参数输出的结果是不一样的,因此我们不能直接将切片作为参数传入函数。
如果我们需要将切片传入一个可变参数的函数中,我们则需要将切片拆解为参数
1 | values := []int{1, 2, 3, 4} |
函数进阶
变量作用域
全局变量
全局变量是定义在函数外部的变量,它在程序整个运行周期内都有效。 在函数中可以访问到全局变量。
1 | package main |
局部变量
局部变量就是仅在自己的代码块中可用的变量
1 | func localVar() { |
函数类型与变量
定义函数类型
使用type
关键字可以定义一个函数类型
1 | type calcFuncType func(int, int) int |
上面语句定义了一个叫calcFuncType类型,它是一种函数类型,这种函数接收两个int类型的参数并且返回一个int类型的返回值。
简而言之,凡是满足接收两个int类型的参数并且返回一个int类型的返回值
都是calcFuncType类型
1 | func add(x, y int) int { |
上面add和sub都是calcFuncType类型
函数类型变量
我们可以声明函数类型的变量并且为该变量赋值
1 | func main() { |
高阶函数
高阶函数分为
- 函数作参数
- 函数作返回值
函数作参数
1 | func calc(x, y int/*第一第二个参数*/, op func(int, int) int/*第三个参数*/) int/*返回值*/ { |
该函数第一第二个参数为操作数,第三个参数为操作。
操作的函数沿用了上面例子的两个函数。
函数作返回值
1 | func do(s string) (func(int, int) int, error) { |
匿名函数
函数内部是不能再定义一个函数的,但是匿名函数是个例外
1 | func(参数)(返回值){ |
匿名函数由于没有函数名,因此不能像普通函数一样调用,它需要保存到某个变量,或者立即执行
1 | //保存到变量 |
匿名函数多用于实现会调函数和闭包。
闭包
闭包简而言之就是函数+引用环境
。
闭包的引用环境包括了:闭包函数内部的非全局变量、常量、函数等。
下面是闭包的一个简单使用:
1 | //把匿名函数作为返回值 |
这个例子非常简单,但是没能体现出闭包函数的作用。
接下来我们展示一个添加后缀名的简单函数,体会一下闭包在其中发挥的作用
1 | func addSuffixFunc(suffix string) func(string) string { |
再看一个更复杂一点的例子
1 | func AddSub(base int) (func(int) int, func(int) int) { |
延迟处理defer
defer关键字可以让后面跟随的语句进行延迟处理。多个defer遵循栈的顺序,即先进后出的顺序。
1 | func main() { |
执行结果如下
1 | start |
Go语言中return语句在底层并不是原子操作,它分为给返回值赋值和RET指令两部。而defer语句的执行实际便是在赋值完成后,RET之前,即先完成计算然后压入栈后等待返回。
由于是将返回值提前压入栈,后续对给返回值赋值的变量作出任何修改都不会对返回值发生任何影响。
1 | x := 10 |
defer延迟调用的特性往往会用在处理资源释放问题上:资源清理、文件关闭、解锁及记录时间等。
推荐文章:https://blog.csdn.net/m0_46251547/article/details/123762669
defer有关面试题
1 | func calc(index string, a, b int) int { |
执行结果是什么?
答案:
1 | A 1 2 3 |
由于defer注册要延迟执行的函数时该函数所有的参数都需要确定其值,因此执行步骤如下
- 执行
calc("A", x, y)
- 将
calc("AA", x, calc("A", x, y))
压入栈 - 执行
calc("B", x, y)
- 将
calc("BB", x, calc("B", x, y))
压入栈 calc("BB", x, calc("B", x, y))
出栈calc("AA", x, calc("A", x, y))
出栈
内置函数
内置函数 | 介绍 |
---|---|
close | 主要用来关闭channel |
len | 用来求长度,比如string、array、slice、map、channel |
new | 用来分配内存,主要用来分配值类型,比如int、struct。返回的是指针 |
make | 用来分配内存,主要用来分配引用类型,比如chan、map、slice |
append | 用来追加元素到数组、slice中 |
panic和recover | 用来做错误处理 |