一个高阶函数应该具备下面至少一个特点:

  • 将一个或者多个函数作为形参
  • 返回一个函数作为其结果

首先明确一件事情:函数名也是一个变量

  1. package main
  2. import (
  3. "fmt"
  4. "reflect"
  5. )
  6. func addCal(x, y int) int {
  7. return x + y
  8. }
  9. func main() {
  10. a := addCal
  11. a(2, 3)
  12. fmt.Println(a) // 0x10a3120
  13. fmt.Println(addCal) // 0x10a3120
  14. fmt.Println(reflect.TypeOf(addCal)) // func(int, int) int
  15. }

结论:函数参数是一个变量,所以,函数名当然可以作为一个参数传入函数体,也可以作为一个返回值。

1、函数参数

  1. func timer(f func()) { // 形参定义是函数类型
  2. timeBefore := time.Now().Unix()
  3. f()
  4. timeAfter := time.Now().Unix()
  5. fmt.Println("运行时间:", timeAfter-timeBefore)
  6. }
  7. func foo() {
  8. fmt.Println("foo function... start")
  9. time.Sleep(time.Second * 2)
  10. fmt.Println("foo function... end")
  11. }
  12. func bar() {
  13. fmt.Println("bar function... start")
  14. time.Sleep(time.Second * 2)
  15. fmt.Println("bar function... end")
  16. }
  17. func main() {
  18. timer(foo) // 传入 foo 函数名
  19. timer(bar) // 传入 bar函数名
  20. }

注意如果函数参数也有参数该怎么写呐?

  1. func add(x, y int) int {
  2. return x + y
  3. }
  4. func mul(x, y int) int {
  5. return x * y
  6. }
  7. // 函数参数必须跟需要传入的函数一样
  8. func cal(f func(x, y int) int, x, y int) int {
  9. return f(x, y)
  10. }
  11. func main() {
  12. ret1 := cal(add, 12, 3)
  13. fmt.Println(ret1)
  14. ret2 := cal(mul, 12, 3)
  15. fmt.Println(ret2)
  16. }

2、函数返回值

  1. package main
  2. import "fmt"
  3. func foo() func() { // 返回一个函数类型
  4. inner := func() { // 函数里面只能嵌套匿名函数
  5. fmt.Println("函数inner执行")
  6. }
  7. return inner
  8. }
  9. func main() {
  10. a := foo() // 返回的匿名函数的地址传给 a
  11. a() // 执行匿名函数逻辑
  12. }