Go语言函数高级篇
- 1.高阶函数
- 函数作为参数
- 函数作为返回值
- 2.匿名函数
- 3.defer
- 4.内置函数
1.高阶函数
高阶函数分为函数作为参数和函数作为返回值两部分。
函数作为参数
函数可以作为参数:
package main
import "fmt"
func add(x, y int) int {
return x + y
}
func mul(x, y int) int {
return x * y
}
func calc(x, y int, op func(int, int) int) int {
return op(x, y)
}
func main() {
res := calc(10, 20, add)
fmt.Println(res) // 30
resP := calc(10, 20, mul)
fmt.Println(resP) // 200
}
函数作为返回值
函数也可以作为返回值:
package main
import (
"errors"
"fmt"
)
func add(x, y int) int {
return x + y
}
func mul(x, y int) int {
return x * y
}
func do(s string) (func(int, int) int, error) {
switch s {
case "+":
return add, nil
case "*":
return mul, nil
default:
return nil, errors.New("无法识别")
}
}
func main() {
f, err := do("+")
fmt.Println(err, f(10, 20)) // <nil> 30
f2, err2 := do("-")
fmt.Println(f2, err2) // <nil> 无法识别
}
2.匿名函数
函数当然还可以作为返回值,但是在Go语言中函数内部不能再像之前那样定义函数了,只能定义匿名函数。匿名函数就是没有函数名的函数,匿名函数的定义格式如下:
func(参数)(返回值){
函数体
}
匿名函数因为没有函数名,所以没办法像普通函数那样调用,所以匿名函数需要保存到某个变量或者作为立即执行函数:
package main
import "fmt"
func main() {
// 将匿名函数保存到变量
add := func(x, y int) {
fmt.Println(x + y)
}
// 调用匿名函数
add(10, 20) // 30
// 自执行函数:匿名函数定义完加()直接执行
func(x, y int) {
fmt.Println(x + y)
}(20, 20) // 40
}
3.defer
Go语言中的defer语句会将其后面跟随的语句进行延迟处理。在defer归属的函数即将返回时,将延迟处理的语句按defer定义的逆序进行执行,也就是说,先被defer的语句最后被执行,最后被defer的语句,最先被执行。
package main
import "fmt"
func main() {
fmt.Println("开始")
defer fmt.Println(1)
defer fmt.Println(2)
defer fmt.Println(3)
fmt.Println("结束")
}
结果:
开始
结束
3
2
1
由于
defer语句延迟调用的特性,所以defer语句能非常方便的处理资源释放问题。比如:资源清理、文件关闭、解锁及记录时间等👕
defer执行时机
在Go语言的函数中return语句在底层并不是原子操作,它分为给返回值赋值和RET指令两步。而defer语句执行的时机就在返回值赋值操作后,RET指令执行前。具体如下图所示:

4.内置函数

panic/recover
Go语言中目前(Go1.12)是没有异常机制,但是使用panic/recover模式来处理错误。 panic可以在任何地方引发,但recover只有在defer调用的函数中有效。 首先来看一个例子:
package main
import "fmt"
func funcA() {
fmt.Println("func A")
}
func funcB() {
panic("panic in B")
}
func funcC() {
fmt.Println("func C")
}
func main() {
funcA()
funcB()
funcC()
}
输出:
func A
panic: panic in B
goroutine 1 [running]:
main.funcB(...)
D:/SystemData/mine/Go-Page/hello.go:10
main.main()
D:/SystemData/mine/Go-Page/hello.go:18 +0x66
Process finished with the exit code 2
程序运行期间funcB中引发了panic导致程序崩溃,异常退出了。这个时候我们就可以通过recover将程序恢复回来,继续往后执行。
package main
import "fmt"
func funcA() {
fmt.Println("func A")
}
func funcB() {
defer func() {
err := recover()
if err != nil {
fmt.Println("recover in B")
}
}()
panic("panic in B")
}
func funcC() {
fmt.Println("func C")
}
func main() {
funcA()
funcB()
funcC()
// func A
// recover in B
// func C
}
recover()必须搭配defer使用defer一定要在可能引发panic的语句之前定义
![论文解析[11] CAT: Cross Attention in Vision Transformer](https://img-blog.csdnimg.cn/5430cf7c7ac040dda1be2310141e623a.png)

![[数据集][VOC][目标检测]河道垃圾水面漂浮物数据集目标检测可用yolo训练-1304张介绍](https://i1.hdslb.com/bfs/archive/5c12f67ab09f89d659e4f816d5cd90be83a7b6ee.jpg@100w_100h_1c.png@57w_57h_1c.png)





![[1.3.3]计算机系统概述——系统调用](https://img-blog.csdnimg.cn/img_convert/caf7058e90fe1b17e2978a4d6c45ec83.png)
![English Learning - L2-4 英音地道语音语调 双元音 [eɪ] [aɪ] [aʊ] [əʊ] [ɔɪ] 2023.03.2 周四](https://img-blog.csdnimg.cn/5f22d48076dd4293b0991e808567e2ad.png)








