Go 学习笔记(16)— 函数(02)[函数类型、有名函数、匿名函数、调用匿名函数、匿名函数赋值给变量、匿名函数做回调函数]
程序员文章站
2022-03-08 23:31:58
...
1. 函数类型
函数类型也叫做函数签名,可以使用 fmt.Printf("%T")
格式化参数打印函数类型。
package main
import "fmt"
func sumTwo(a []int) (ret int) {
for _, v := range a {
ret += v
}
return
}
func main() {
n := []int{1, 2, 3, 4, 5}
result := sumTwo(n)
fmt.Println("result is ", result) // result is 15
fmt.Printf("sumTwo type is %T\n", sumTwo) // sumTwo type is func([]int) int
}
两个函数类型相同的条件是:拥有相同的形参列表和返回值列表,其中列表元素的次序、个数和类型都相同,形参名称可以不相同。
2. 有名函数
有名函数是指函数有具体的名称,有名函数的函数名可以看作函数类型的常量,可以直接使用函数名调用函数,也可以直接赋值给函数类型变量,可以通过该变量来调用该函数。
package main
import "fmt"
func sum(a, b int) int {
fmt.Println("I am in sum function")
return a + b
}
func main() {
sum(3, 10) // 直接调用
result := sum(3, 4)
fmt.Println("result is ", result)
f := sum // 有名函数可以直接赋值给变量
ret := f(3, 10) // 通过该变量来调用该函数
fmt.Println("ret is ", ret)
}
3. 匿名函数
匿名函数是指不需要定义函数名的一种函数实现方式,由一个不带函数名的函数声明和函数体组成。
匿名函数顾名思义就是函数没有名称,匿名函数可以直接赋值给变量,可以当作实参,也可以作为返回值,还可以直接被调用。
匿名函数的定义格式如下:
func(参数列表)(返回参数列表){
函数体
}
匿名函数的定义就是没有名字的普通函数定义。
3.1 在定义时调用匿名函数
匿名函数可以在声明后调用,例如:
func main() {
func(data int) {
fmt.Println("hello", data)
}(100) // }后的(100),表示对匿名函数进行调用,传递参数为 100。
}
3.2 将匿名函数赋值给变量
匿名函数可以被赋值,例如:
// 将匿名函数体保存到f()中
f := func(data int) {
fmt.Println("hello", data)
}
// 使用f()调用
f(100)
3.3 匿名函数用作回调函数
下面的代码实现对切片的遍历操作,遍历中访问每个元素的操作使用匿名函数来实现,用户传入不同的匿名函数体可以实现对元素不同的遍历操作,代码如下:
package main
import (
"fmt"
)
// 遍历切片的每个元素, 通过给定函数进行元素访问
func visit(list []int, f func(int)) {
for _, v := range list {
f(v)
}
}
func main() {
// 使用匿名函数打印切片内容,// 匿名函数作为实参
visit([]int{1, 2, 3, 4}, func(v int) {
fmt.Println(v)
})
}
### 3.4 匿名函数实现操作封装
下面这段代码将匿名函数作为 map 的键值,通过命令行参数动态调用匿名函数,代码如下:
package main
import (
"flag"
"fmt"
)
//定义命令行参数 skill,从命令行输入 --skill 可以将 = 后的字符串传入 skillParam 指针变量。
var skillParam = flag.String("skill", "", "skill to perform")
func main() {
// 解析命令行参数,解析完成后,skillParam 指针变量将指向命令行传入的值。
flag.Parse()
// 定义一个从字符串映射到 func() 的 map,然后填充这个 map
var skill = map[string]func(){
"fire": func() { // 初始化 map 的键值对,值为匿名函数。
fmt.Println("chicken fire")
},
"run": func() {
fmt.Println("soldier run")
},
"fly": func() {
fmt.Println("angel fly")
},
}
/* skillParam 是一个 *string 类型的指针变量,
使用 *skillParam 获取到命令行传过来的值,并在 map 中查找对应命令行参数指定的字符串的函数。
*/
if f, ok := skill[*skillParam]; ok {
f()
} else {
fmt.Println("skill not found")
}
}
运行结果如下:
PS D:\code> go run main.go --skill=fly
angel fly
PS D:\code> go run main.go --skill=run
soldier run
3.5 匿名函数其它示例
package main
import "fmt"
// 匿名函数直接赋值给变量
var sum = func(a, b int) int {
return a + b
}
// 匿名函数作为返回值
func swap(str string) func(int, int) int {
if str == "add" {
return func(a, b int) int {
return a + b
}
}
if str == "sub" {
return func(a, b int) int {
return a - b
}
}
return nil
}
func input(f func(int, int) int, a, b int) int {
return f(a, b)
}
func main() {
// 匿名函数作为实参
z := input(func(x, y int) int {
return x + y
}, 10, 20)
fmt.Println("z is ", z)
fmt.Println("sum(1, 3) is ", sum(1, 3))
fmt.Println("swap(1, 3) is ", swap("sub")(1, 10))
}
输出:
z is 30
sum(1, 3) is 4
swap(1, 3) is -9
匿名函数可赋值给变量,做为结构字段,或者在 channel 里传送。
package main
func main() {
// --- function variable ---
fn := func() { println("Hello, World!") }
fn()
// --- function collection ---
fns := [](func(x int) int){
func(x int) int { return x + 1 },
func(x int) int { return x + 2 },
}
println(fns[0](100))
// --- function as field ---
d := struct {
fn func() string
}{
fn: func() string { return "Hello, World!" },
}
println(d.fn())
// --- channel of function ---
fc := make(chan func() string, 2)
fc <- func() string { return "Hello, World!" }
println((<-fc)())
}
输出:
Hello, World!
101
Hello, World!
Hello, World!
上一篇: php匿名函数如何调用外部变量
下一篇: 几种基础的jquery选择器