go匿名函数

定义

Go中的匿名函数和PHP类似,区别就是在Go中参数以及返回值的类型必须声明

匿名函数同样被称之为闭包(函数式语言的术语):它们被允许调用定义在其它环境下的变量。闭包可使得某个函数捕捉到一些外部状态,例如:函数被创建时的状态。另一种表示方式为:一个闭包继承了函数所声明时的作用域。这种状态(作用域内的变量)都被共享到闭包的环境中,因此这些变量可以在闭包中被操作,直到被销毁

1
2
3
func(a,b int) int {
return a+b
}(1,2) //最后直接带上括号代表直接执行此匿名函数

应用

将匿名函数作为返回值

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

import "fmt"

func main() {
p2 := Add2()
fmt.Println(p2(3))

add2 := Adder(1)
fmt.Println(add2(3))
}

func Add2() func(b int) int {
return func(b int) int {
return b + 2
}
}

func Adder(a int) func(b int) int {
return func(b int) int {
return a + b
}
}
// 5
// 4

保证局部变量安全性

闭包内部声明的局部变量无法从外部修改,从而确保了安全性(类似类的私有属性):

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

import "fmt"

var j int = 1


func main() {
f := func() {
var i int = 1
fmt.Printf("i, j: %d, %d\n", i, j)
}
f()
j += 2
f()
}
//i, j: 1, 1
//i, j: 1, 3
// i为匿名函数内部变量,外部无法修改,j为外部变量,可以修改

匿名函数作为参数

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

import "fmt"

func main() {
i := 10
add := func(a, b int) {
fmt.Println("外部变量i:",i)
fmt.Println("作为参数传递到外部函数,参数a:",a,"参数b:",b,"返回值:",a + b)
}
callback(1,add)
}

func callback(x int ,f func(int,int)) {
f(x,2)
}

//外部变量i: 10
//作为参数传递到外部函数,参数a: 1 参数b: 2 返回值: 3

使用闭包调试

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

import (
"log"
"runtime"
)

func main() {
where := func() {
_, file, line, _ := runtime.Caller(1)
log.Printf("%s:%d", file, line)
}
where()
log.SetFlags(log.Lshortfile)
log.Print("Log包获取文件短信息")
log.SetFlags(log.Llongfile)
log.Print("log包获取文件长信息")
// 2019/07/11 16:42:03 /path/go/calc/src/1.go:13
// 1.go:15: Log包获取文件短信息
/// /path/go/calc/src/1.go:17: log包获取文件长信息
}