共计 2384 个字符,预计需要花费 6 分钟才能阅读完成。
1. 用 type 关键字能够定义函数类型,函数类型变量能够作为函数的参数或返回值。
package main
import "fmt"
func add(a, b int) int {return a + b}
func sub(a, b int) int {return a - b}
type Task func(int, int) int
func exec(t Task, a, b int) int {return t(a, b)
}
func main() {a := exec(add, 10, 20)
fmt.Println(a)
b := exec(sub, 100, 95)
fmt.Println(b)
}
解析:type Task func(int, int) int,这句是说,应用 type 关键字定义 1 个类型为 func 的 Task,这个 func 有 2 个 int 形参、1 个 int 返回值。再看 exec 这个函数,它有 3 个形参,形参 t 的类型是刚定义的函数类型 Task,另外两个你懂的,我就不说了。
2. 匿名函数的玩法是真的骚,看看骚在哪里
-
栗子 1:匿名函数能够间接赋给变量
func main() {var aaa = func(a, b int) int {return a + b} ret := aaa(89, 78) fmt.Println(ret) }
输入:
167
-
栗子 2:匿名函数作为函数入参
这个例子感觉跟方才应用 type 关键字定义函数类型的例子有点雷同的赶脚,认真一看,如同也只是在应用的形式上是一样,定义函数的套路又是不同的。
func work(f func(int, int) int, a, b int) int {return f(a, b) } func add(a, b int) int {return a + b} func main() {a := work(add, 100, 200) fmt.Println(a) }
输入:
300
解析:形参 f 的类型就是匿名函数,持续看 func(int, int) int,这个匿名函数接管两个 int 形参,返回值也是 int 类型。另外两个形参 a 和 b,也是 int,想必你懂了,我就不废话了。
-
栗子 3:匿名函数作为函数出参
匿名函数作为函数出参(作为函数返回值),经一直调测,有 3 种骚包玩法,爽死了。
-
骚包玩法 1
// 先来个简略的 func work() func() int {return func() int {return 10 + 20} } func main() {f := work() ret := f() fmt.Println(ret) }
输入:
30
-
骚包玩法 2
// 再革新下 func work(a, b int) func() int {return func() int {return a + b} } func main() {f := work(500, 20) ret := f() fmt.Println(ret) }
输入:
520
-
骚包玩法 3
// 再次革新 func work() func(int, int) int {return func(a, b int) int {return a + b} } func main() {f := work() ret := f(600, 50) fmt.Println(ret) }
输入:
650
-
对 3 种骚包玩法的简略解析:
再这里就解析一下第 3 种玩法,能搞懂这个玩法,后面 2 个玩法,你就天然懂了。work 函数没有入参,然而有出参(也能够说是返回值),出参是匿名函数 func(int, int) int,这个定义在返回值里的匿名函数有 2 个 int 类型的形参(入参)和 1 个 int 类型的返回值。再看看函数体外部,没干很简单活儿,而是间接 return 了匿名函数,函数体里的这个匿名函数是和定义在返回值里的类型保持一致的,也是接管了 2 个 int 的形参 a 和 b,返回值也是 int,啥也没干,就做了个相加。好郁闷!不晓得你看懂了没?再看看是如何应用 work 函数的,关键点就在这里,调用 work()赋给了变量 f,这时候,f 它就是一个函数了,再调用 f(600, 50),想必你曾经晓得了为啥要传入 2 个 int 值,这下搞定!不晓得把你绕晕没,这玩法的确很骚。
3. 匿名函数和提早调用
提早调用的规定是:依照 先进后出 的程序,也就是说函数返回前是会被执行的,而且是依照先进后出的程序。如何起到提早的成果,是须要注册的,可通过 defer 关键字进行注册。那么什么场景下须要用到提早调用呢?比方常见的场景:当一个函数被行将执行完后,也就是实现工作的最初一刻,须要回收和开释某些资源。
提早调用的机制能够配合匿名函数来应用,这样就能够让匿名函数被间接调用,只能说是真的骚。
先看个小栗子:
package main
import "fmt"
func work() bool {fmt.Println("函数开始工作...")
defer func() {fmt.Println("回收相干资源工作开始!")
}()
defer func() {fmt.Println("清理工作开始!")
}()
fmt.Println("函数正在工作...")
fmt.Println("函数工作结束...")
return true
}
func main() {status := work()
fmt.Println(status)
}
输入:
函数开始工作...
函数正在工作...
函数工作结束...
清理工作开始!回收相干资源工作开始!true
在下面的栗子中,定义了个 work 函数,先看看输入的后果,感触下。在 work 函数中,注册了两个提早调用,work 函数从开始 -> 正在 -> 结束,完结后才执行 defer 注册的匿名函数,这里要着重留神提早调用规定:先进后出,也就是先注册后执行。“回收相干资源工作”是先注册的,他的执行程序排在了“清理工作”的前面。感触到了吗?
最初阐明一下:defer 关键字让匿名函数实现了可间接调用,那么应用 defer 注册提早调用时要留神,defer 关键字的前面肯定是要函数或办法的调用,不能间接写语句哦。
本文转载于(喜爱的盆友关注咱们):https://mp.weixin.qq.com/s/Dt…