总结的含乱
- 断言
package main
import (
"fmt"
)
func main() {
a := "along"
var num interface{}
num = a
fmt.Println(a)
value, ok := num.(string)
if ok != false{
fmt.Println("ok")
}
fmt.Println(value)
}
输出
along
ok
along
- 匿名函数
package main
import (
"fmt"
)
func main() {
//匿名函数
func(data int) {
fmt.Println("hello", data)
}(100)
}
- 将匿名函数赋值给变量
匿名函数可以被赋值,例如:
// 将匿名函数体保存到f()中
f := func(data int) {
fmt.Println("hello", data)
}
// 使用f()调用
f(100)
匿名函数的用途非常广泛,它本身就是一种值,可以方便地保存在各种容器中实现回调函数和操作封装。
- 匿名函数作回调函数
package main
import (
"fmt"
)
// 遍历切片的每个元素, 通过给定函数进行元素访问
func visit(list []int, f func(int)) {
for _, v := range list {
f(v)
}
}
func main() {
//定义一个匿名函数
f := func(v int) {
fmt.Println(v)
}
// 使用匿名函数打印切片内容
visit([]int{1, 2, 3, 4}, f)
}
下面写法等价
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)
})
}
代码说明如下:
- 使用 visit() 函数将整个遍历过程进行封装,当要获取遍历期间的切片值时,只需要给 visit() 传入一个回调参数即可。
- 定义了一个匿名函数,作用是将遍历的每个值打印出来。
- 准备一个整型切片 []int{1,2,3,4} 传入 visit() 函数作为遍历的数据。
- 使用匿名函数实现操作封装
将匿名函数放到 map 中,通过命令行参数动态调用匿名函数,代码如下:
package main
import (
"flag"
"fmt"
)
var skillParam = flag.String("skill", "", "skill to perform")
func main() {
flag.Parse()
var skill = map[string]func(){
"fire": func() {
fmt.Println("chicken fire")
},
"run": func() {
fmt.Println("soldier run")
},
"fly": func() {
fmt.Println("angel fly")
},
}
if f, ok := skill[*skillParam]; ok {
f()
} else {
fmt.Println("skill not found")
}
}
输出
go run main.go --skill=fly
angel fly
代码说明如下:
- 第 8 行,定义命令行参数 skill,从命令行输入 --skill 可以将=后的字符串传入 skillParam 指针变量。
- 第 12 行,解析命令行参数,解析完成后,skillParam 指针变量将指向命令行传入的值。
- 第 14 行,定义一个从字符串映射到 func() 的 map,然后填充这个 map。
- 第 15~23 行,初始化 map 的键值对,值为匿名函数。
- 第 26 行,skillParam 是一个 *string 类型的指针变量,使用 *skillParam 获取到命令行传过来的值,并在 map 中查找对应命令行参数指定的字符串的函数。
- 第 29 行,如果在 map 定义中存在这个参数就调用,否则打印“技能没有找到”
回调函数
参考: Golang回调函数实例二则
完整摘抄如下
1.定义
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。不太懂,是和puthon的闭包类似吗? python闭包就是把一个函数(可以理解为函数地址)返回,在使用的时候才真正取用内层函数。
2.机制
定义一个回调函数
- 提供函数实现的一方在初始化的时候,将回调函数的函数指针注册给调用者
- 当特定的事件或条件发生时,调用者使用函数指针
调
回调函数对事件进行处理
例1.这是一个简单的回调例子,调用函数test时,调用真正的实现函数add
package main
import "fmt"
type Callback func(x, y int) int
// 提供一个接口,让外部去实现
func test(x, y int, callback Callback) int {
return callback(x, y)
}
// 回调函数的具体实现
func add(x, y int) int {
return x + y
}
func main() {
x, y := 1, 2
fmt.Println(test(x, y, add))
}
例2.这是一个将字符串转为Int的例子,在转换失败的情况下执行回调函数,输出错误信息
package main
import (
"fmt"
"strconv"
)
type Callback func(msg string)
//将字符串转换为int64,如果转换失败调用Callback
func stringToInt(s string, callback Callback) int64 {
if value, err := strconv.ParseInt(s, 0, 0); err != nil {
callback(err.Error())
return -1
} else {
return value
}
}
// 记录日志消息的具体实现
func errLog(msg string) {
fmt.Println("Convert error: ", msg)
}
func main() {
fmt.Println(stringToInt("18", errLog))
fmt.Println(stringToInt("hh", errLog))
}
输出
18
Convert error: strconv.ParseInt: parsing "hh": invalid syntax
-1
专门找了一篇文章学习,参考:Go基础系列:函数(2)——回调函数和闭包
当函数具备以下两种特性的时候,就可以称之为高阶函数(high order functions):
- 函数可以作为另一个函数的参数(典型用法是回调函数)
- 函数可以作为另一个函数的返回值(典型用法是闭包)
将函数B作为另一个函数A的参数,可以使得函数A的通用性更强,可以随意定义函数B,只要满足规则,函数A都可以去处理,这比较适合于回调函数。
注: 上面这句话的意思是A(排序)可以用多个B(升序、降序)
回调例子
package main
import (
"fmt"
"sort"
)
func main() {
s1 := []int{112, 22, 52, 32, 12}
// 定义降序排序函数
less := func(i, j int) bool {
return s1[i] > s1[j]
}
// 定义升序排序函数
less2 := func(i, j int) bool {
return s1[i] < s1[j]
}
//传谁是谁
sort.SliceStable(s1, less)
fmt.Println(s1)
//另一种传法
sort.SliceStable(s1, less2)
fmt.Println(s1)
}
结果
[112 52 32 22 12]
[12 22 32 52 112]