当我们不希望给函数起名字的时候,可以使用匿名函数,例如:func(x, y int) int { return x + y }。
这样的一个函数不能够独立存在(编译器会返回错误:non-declaration statement outside function body),但可以被赋值于某个变量,即保存函数的地址到变量中:fplus := func(x, y int) int { return x + y },然后通过变量名对函数进行调用:fplus(3,4)。
当然,您也可以直接对匿名函数进行调用:func(x, y int) int { return x + y } (3, 4)。
packagemainimport"fmt"funcmain(){f()}funcf(){fori:=0;i<4;i++{g:=func(iint){fmt.Printf("%d",i)}//此例子中只是为了演示匿名函数可分配不同的内存地址,在现实开发中,不应该把该部分信息放置到循环中。g(i)fmt.Printf(" - g is of type %T and has value %v\n",g,g)}}
输出:
我们可以看到变量 g 代表的是 func(int),变量的值是一个内存地址。
所以我们实际上拥有的是一个函数值:匿名函数可以被赋值给变量并作为值使用。
练习 6.8 在 main 函数中写一个用于打印 Hello World 字符串的匿名函数并赋值给变量 fv,然后调用该函数并打印变量 fv 的类型。
匿名函数像所有函数一样可以接受或不接受参数。下面的例子展示了如何传递参数到匿名函数中:
请学习以下示例并思考(return_defer.go):函数 f 返回时,变量 ret 的值是什么?
变量 ret 的值为 2,因为 ret++ 是在执行 return 1 语句后发生的。
这可用于在返回语句之后修改返回的 error 时使用。
defer 语句和匿名函数
关键字 defer (详见第 6.4 节)经常配合匿名函数使用,它可以用于改变函数的命名返回值。
匿名函数还可以配合 go 关键字来作为 goroutine 使用(详见第 14 章和第 16.9 节)。
0 - g is of type func(int) and has value 0x681a80
1 - g is of type func(int) and has value 0x681b00
2 - g is of type func(int) and has value 0x681ac0
3 - g is of type func(int) and has value 0x681400