文章首发于:clawhub.club


这篇文章纯纯的借鉴加复制,参考了Go 系列教程 —— 33. 函数是一等公民(头等函数)
虽然说java现在也支持了链式编程,但是对头等函数方面还是很陌生的。

定义

支持头等函数(First Class Function)的编程语言,可以把函数赋值给变量,也可以把函数作为其它函数的参数或者返回值。Go 语言支持头等函数的机制。

匿名函数

没有名称的函数称为匿名函数(Anonymous Function),要调用一个匿名函数,可以不用赋值给变量。还可以向匿名函数传递参数。

1
2
3
4
5
6
7
8
9
10
11
package main

import (
"fmt"
)

func main() {
func(n string) {
fmt.Println("Welcome", n)
}("Gophers")
}

用户自定义的函数类型

和定义结构体一样,可以定义函数类型,就像HandlerFunc一样。

1
2
// HandlerFunc defines the handler used by gin middleware as return value.
type HandlerFunc func(*Context)

参考个更简单的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main

import (
"fmt"
)

type add func(a int, b int) int

func main() {
var a add = func(a int, b int) int {
return a + b
}
s := a(5, 6)
fmt.Println("Sum", s)
}

高阶函数

wiki 把高阶函数(Hiher-order Function)定义为:满足下列条件之一的函数

  • 接收一个或多个函数作为参数
  • 返回值是一个函数

把函数作为参数,传递给其它函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package main

import (
"fmt"
)

func simple(a func(a, b int) int) {
fmt.Println(a(60, 7))
}

func main() {
f := func(a, b int) int {
return a + b
}
simple(f)
}

在其它函数中返回函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package main

import (
"fmt"
)

func simple() func(a, b int) int {
f := func(a, b int) int {
return a + b
}
return f
}

func main() {
s := simple()
fmt.Println(s(60, 7))
}

闭包

闭包(Closure)是匿名函数的一个特例。当一个匿名函数所访问的变量定义在函数体的外部时,就称这样的匿名函数为闭包。每一个闭包都会绑定一个它自己的外围变量(Surrounding Variable)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package main

import (
"fmt"
)

func appendStr() func(string) string {
t := "Hello"
c := func(b string) string {
t = t + " " + b
return t
}
return c
}

func main() {
a := appendStr()
b := appendStr()
fmt.Println(a("World"))
fmt.Println(b("Everyone"))

fmt.Println(a("Gopher"))
fmt.Println(b("!"))
}

头等函数的实际用途

如果我们希望将切片中的所有整数乘以 5,并返回出结果,那么通过头等函数可以很轻松地实现。我们把这种对集合中的每个元素进行操作的函数称为 map 函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package main

import (
"fmt"
)

func iMap(s []int, f func(int) int) []int {
var r []int
for _, v := range s {
r = append(r, f(v))
}
return r
}
func main() {
a := []int{5, 6, 7, 8, 9}
r := iMap(a, func(n int) int {
return n * 5
})
fmt.Println(r)
}

该程序会输出:

1
[25 30 35 40 45]