go总结:匿名函数

总结的含乱

  1. 断言
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
  1. 匿名函数
package main

import (
	"fmt"
)

func main() {
	//匿名函数
	func(data int) {
		fmt.Println("hello", data)
	}(100)
}
  1. 将匿名函数赋值给变量

匿名函数可以被赋值,例如:

// 将匿名函数体保存到f()中
f := func(data int) {
    fmt.Println("hello", data)
}
// 使用f()调用
f(100)

匿名函数的用途非常广泛,它本身就是一种值,可以方便地保存在各种容器中实现回调函数和操作封装。

  1. 匿名函数作回调函数
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() 函数作为遍历的数据。
  1. 使用匿名函数实现操作封装

匿名函数放到 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]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值