一个高阶函数应该具备下面至少一个特点:
- 将一个或者多个函数作为形参
- 返回一个函数作为其结果
首先明确一件事情:函数名也是一个变量
package mainimport ("fmt""reflect")func addCal(x, y int) int {return x + y}func main() {a := addCala(2, 3)fmt.Println(a) // 0x10a3120fmt.Println(addCal) // 0x10a3120fmt.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 mainimport "fmt"func foo() func() { // 返回一个函数类型inner := func() { // 函数里面只能嵌套匿名函数fmt.Println("函数inner执行")}return inner}func main() {a := foo() // 返回的匿名函数的地址传给 aa() // 执行匿名函数逻辑}
