详解Go中匿名函数,闭包函数,回调函数

匿名函数

  • 匿名函数没有函数名,只有函数体,函数可以被作为一种类型被赋值给变量,匿名函数也往往以变量的方式被传递。
  • 匿名函数经常被用于实现回调函数、闭包等。
  • 定义格式如下:

func(参数列表)(返回参数列表){
   //函数体
}
  • 方式一:在定义时调用匿名函数
func anonymousFunc1() {
	func(data int) {
		fmt.Println("hello", data)
	}(100)
}

这里的100是匿名函数的参数

  • 方式二:将匿名函数赋值给变量
func anonymousFunc2()  {
f := func(data string) {
	fmt.Println(data)
}
f("heelo")
}
i2 := func(x, y int) int { return x + y }(1,2)

如上,定义一个匿名函数,包含两个参数x,y。返回x+y的结果。后面(),里面表示参数,参数是:x=1,y=2

当然你也可以先定义匿名函数,不使用,等你需要使用的时候,像调用函数一样传参数就可以:

func anonymousFunc5() {

	var x, y int
	x = 1
	y = 2
	i2 := func(x, y int) int { return x + y }
	i3 := i2(x, y)
	fmt.Println(i3)
}

两种函数的区别在于(x,y)参数在哪里。

  • 方式三:有返回参数的后面必须有return
func anonymousFunc3()  {
	aaa := func(data int) int {
		return data
	}
	fmt.Println(aaa(1))
}

闭包函数

在代码中,函数若f2被包括在函数f1内部,这时f1内部的所有局部变量,对f2都是可见的。但反过来就不行,f2的局部变量对f1是不可见的。这就是:链式调用

因为fs2可以读取f1中的局部变量,所以只要把f2作为返回值,我们就可以在f1外部读取f2的内部变量了

闭包:定义在函数内部的函数,在本质上,闭包是将函数内部(f2的变量)和函数外部(f1的变量)连接起来的桥梁(在go语言中匿名函数就是闭包)
闭包的实现:确保只要闭包在使用,那么被闭包引用的变量会一直存在

闭包经常用于回调函数,当IO操作(例如从网络获取数据、文件读写)完成的时候,会对获取的数据进行某些操作,这些操作可以交给函数对象处理。

func test()  {
	a := 5
	b := func()(func()){
		c := 10
		return func() {
			fmt.Printf("a,c: %d,%d \n",a,c)
			a *= 3
		}
	}()
	b()
	println(a)
}
输出:
a,c: 5,10 
15

解释一下
匿名函数的返回值是一个匿名函数,return返回的是一个匿名函数,注意没有加(),所以是用return接收。
然后在最外层加了()。所以将匿名函数的值给了b。注意了此时的b其实是一个函数如下图所示,所以调用的时候是b()
在这里插入图片描述

尝试将匿名函数的最外层的()去掉:

func test()  {
	a := 5
	b := func()(func()){
		c := 10
		return func() {
			fmt.Printf("a,c: %d,%d \n",a,c)
			a *= 3
		}
	}
	fmt.Printf("打印b()类型为:%T\n打印b()值为%v\n",b(),b())
	println(a)
输出:
打印b()类型为:func()
打印b()值为0x477180
5
}

此时b的是一个值,类型如下所示:
在这里插入图片描述
在试一下b()()打印:

func test()  {
	a := 5
	b := func()(func()){
		c := 10
		return func() {
			fmt.Printf("a,c: %d,%d \n",a,c)
			a *= 3
		}
	}
	b()()
	println(a)
}
输出:
a,c: 5,10
15

b()()为函数,
注意:a在匿名函数内是可以引用的,但是你如果在匿名函数外引用c,你会发现找不到。并且在闭包内改变了a的值也是会作用到a真实的内存地址中的。

回调函数:

回调函数就是一个被作为参数传递的函数。

package main

import (
	"fmt"
)

func main() {
	arr :=[]float64{1,2,3,4,5,6}
	a :=filterSlice(arr, func(f float64) string {
	return fmt.Sprint(f)

	})
	fmt.Println("a",a)
	anonymousFunc()
}

type myFunc1 func(f float64) string

//作为回调函数
//先遍历一个切片,对切片进行操作的函数
func filterSlice(arr []float64, f myFunc1) []string {
	//定义一个切片类型的字符串
	var result []string
	for _, val := range arr {
		result = append(result, f(val))
	}
	fmt.Println("result",result)
	return result
}
//对这个函数进行回调使用
//1.回调函数就是一个被作为参数传递的函数
//2.函数中有一个参数是函数,这个函数就是回调函数
func anonymousFunc()  {
	arr :=[]float64{9,8,7,6,5,4,3,2,1,0}
	filterSlice(arr, func(f float64) string {
		return fmt.Sprint(f)
	})
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值