一个高阶函数应该具备下面至少一个特点:
- 将一个或者多个函数作为形参
- 返回一个函数作为其结果
首先明确一件事情:函数名也是一个变量
package main
import (
"fmt"
"reflect"
)
func addCal(x, y int) int {
return x + y
}
func main() {
a := addCal
a(2, 3)
fmt.Println(a) // 0x10a3120
fmt.Println(addCal) // 0x10a3120
fmt.Println(reflect.TypeOf(addCal)) // func(int, int) int
}
结论:函数参数是一个变量,所以,函数名当然可以作为一个参数传入函数体,也可以作为一个返回值。
1、函数参数
func timer(f func()) { // 形参定义是函数类型
timeBefore := time.Now().Unix()
f()
timeAfter := time.Now().Unix()
fmt.Println("运行时间:", timeAfter-timeBefore)
}
func foo() {
fmt.Println("foo function... start")
time.Sleep(time.Second * 2)
fmt.Println("foo function... end")
}
func bar() {
fmt.Println("bar function... start")
time.Sleep(time.Second * 2)
fmt.Println("bar function... end")
}
func main() {
timer(foo) // 传入 foo 函数名
timer(bar) // 传入 bar函数名
}
注意如果函数参数也有参数该怎么写呐?
func add(x, y int) int {
return x + y
}
func mul(x, y int) int {
return x * y
}
// 函数参数必须跟需要传入的函数一样
func cal(f func(x, y int) int, x, y int) int {
return f(x, y)
}
func main() {
ret1 := cal(add, 12, 3)
fmt.Println(ret1)
ret2 := cal(mul, 12, 3)
fmt.Println(ret2)
}
2、函数返回值
package main
import "fmt"
func foo() func() { // 返回一个函数类型
inner := func() { // 函数里面只能嵌套匿名函数
fmt.Println("函数inner执行")
}
return inner
}
func main() {
a := foo() // 返回的匿名函数的地址传给 a
a() // 执行匿名函数逻辑
}