go-函数式编程与闭包

函数式编程

函数变量

在go语言中,函数可以赋值给一个变量,使用变量调用函数方法

函数定义

package _case

import "errors"

func Sum(a, b int) (sum int, err error) {
	if a <= 0 && b <= 0 {
		err = errors.New("两数相加要求两数不能同时小于等于0")
		return 0, err
	}

	sum = a + b

	return
}

调用函数

	f1 := _case.Sum              //将Sum方法赋值给变量f1
	//执行函数
	fmt.Println(f1(2, 3)) //5 <nil>

实现中间件

将函数作为输入输出实现中间件

// SumFunc 将函数作为类型
type SumFunc func(a int, b int) (int, error) //SumFunc代表Sum方法

// LogMiddleware 将函数作为输入输出实现中间件
func LogMiddleware(in SumFunc) SumFunc { //in 是一个变量, 代表函数方法Sum
	//返回函数为闭包函数,其中in为闭包函数使用的外部函数的内部变量
	return func(a, b int) (int, error) {
		log.Printf("日志中间件,记录操作数: a: %d, b : %d", a, b)
		return in(a, b)
	}
}

调用中间件

	//将函数作为输入输出实现中间件
	f2 := _case.LogMiddleware(_case.Sum)
	fmt.Println(f2(1, 2))	
	/*2023/09/04 12:34:36 日志中间件,记录操作数: a: 1, b : 2
	3 <nil>
	*/

再次附加中间件可以打印两次日志,中间件可以叠加

	//将函数作为输入输出实现中间件
	f2 := _case.LogMiddleware(_case.Sum)
	//再次附加中间件
	f2 = _case.LogMiddleware(f2)
	fmt.Println(f2(1, 2))
	/*
	2023/09/04 12:36:53 日志中间件,记录操作数: a: 1, b : 2
	2023/09/04 12:36:53 日志中间件,记录操作数: a: 1, b : 2
	3 <nil>
	*/

使用函数类型作为对象实现方法

// Accumulation 将函数作为对象添加实现方法
func (sum SumFunc) Accumulation(list ...int) (int, error) { //将可变参数list中的数相加
	s := 0
	var err error
	for _, i := range list { //遍历列表
		s, err = sum(s, i) //使用s存储相加的值,调用SunFunc函数类型对象
		if err != nil {
			return s, err
		}
	}
	return s, err
}

调用方法

	f1 := _case.Sum //将Sum方法赋值给变量f1
	f2 := _case.LogMiddleware(_case.Sum)

	f3 := _case.SumFunc(f1) //f3 为Sum函数方法的对象
	fmt.Println(f3.Accumulation(1, 2, 3, 4))

	f3 = _case.SumFunc(f2) //f2 返回的也是SunFunc类型
	fmt.Println(f2.Accumulation(1, 2, 3, 4, 5))
	/*
		2023/09/04 12:52:24 日志中间件,记录操作数: a: 0, b : 1
		2023/09/04 12:52:24 日志中间件,记录操作数: a: 1, b : 2
		2023/09/04 12:52:24 日志中间件,记录操作数: a: 3, b : 3
		2023/09/04 12:52:24 日志中间件,记录操作数: a: 6, b : 4
		2023/09/04 12:52:24 日志中间件,记录操作数: a: 10, b : 5
		15 <nil>
	*/

闭包

闭包在Go语言中是一种强大的特性,它可以定义匿名函数,并且可以访问其所在作用域的变量。当一个函数返回一个内部的匿名函数时,这个匿名函数可以访问并持有原函数的局部变量,这种方式就形成了闭包。

func adder() func(int) int {
	sum := 0
	return func(x int) int {
		sum += x
		return sum
	}
}

func main() {
	addFunc := adder()
	fmt.Println(addFunc(1)) // 输出 1
	fmt.Println(addFunc(2)) // 输出 3
	fmt.Println(addFunc(3)) // 输出 6
}

在上面的示例中,adder 函数返回了一个匿名函数,这个匿名函数可以访问并修改 adder 函数中的局部变量 sum。每次调用 addFunc 函数时,都会将传入的值累加到 sum 上,并返回当前的累加结果。

最佳实现

使用闭包实现获取斐波那契数列第n个数

package _case

import "log"

func Fib(n int) int {
	if n <= 2 {
		log.Fatal("请选择大于2的位置,前两个位置已经有值")
	}
	t := tool()
	var res int
	for i := 0; i < n-2; i++ { //循环中闭包没有结束,t()中值没有释放,一直使用计算后的值
		res = t() //t()为闭包方法
	}
	return res
}

// 斐波那契数列 X0 + X1 = X2 ...求Xn
func tool() func() int { //当闭包函数结束后变量才释放
	var x0 = 1
	var x1 = 1
	var x2 = 0
	return func() int {
		x2 = x0 + x1 //x0, x1, x2 全部是匿名函数引用函数作用域外的变量,形成了闭包
		x0 = x1
		x1 = x2
		return x2
	}

}

闭包陷阱

闭包函数

func ClosureTrap() {
	for i := 0; i < 10; i++ {
		go func() {
			fmt.Println(i) //内部匿名函数引用了外部函数的变量,形成了闭包
		}()
	}
}

函数调用

	//闭包的陷阱
	_case.ClosureTrap()
	ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, os.Kill)
	//使用signal.NotifyContext()函数创建一个上下文,并设置监听的操作系统信号为os.Interrupt和os.Kill,表示监听操作系统的中断信号。
	//使用defer关键字和cancel()函数保证在函数执行完毕后会调用取消上下文的操作。
	//使用<-ctx.Done()语句,会阻塞代码的执行,直到上下文被取消(即接收到操作系统中断信号),此时ctx.Done()的通道会有一个值发送。
	defer cancel()
	<-ctx.Done()

问题解决

func ClosureTrap() {
    for i := 0; i < 10; i++ {
        go func(num int) {
            fmt.Println(num)
        }(i)
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
闭包函数是指内部函数可以访问外部函数的局部变量,并且在外部函数执行结束后,依然可以访问和修改这些变量。在Go语言中,函数也可以作为返回值返回,形成闭包闭包函数可以用来实现函数式编程的一些特性。 函数式编程是一种编程范式,它将计算过程看作是一系列函数的应用。在函数式编程中,函数被视为一等公民,可以像其他数据类型一样传递、赋值和返回。函数式编程强调使用纯函数,即不依赖于外部状态和副作用的函数,这样可以提高代码的可读性、可维护性和并发性。 在Go语言中,闭包函数和函数式编程可以结合使用。通过闭包函数,我们可以在函数内部定义其他函数,并且这些内部函数可以访问外部函数的局部变量。这样就可以实现一些函数式编程的特性,例如高阶函数、柯里化和函数组合等。 以下是一个示例代码,演示了Go语言闭包函数和函数式编程的用法: ```go package main import "fmt" // 返回一个闭包函数,用于累加计数 func counter() func() int { count := 0 return func() int { count++ return count } } // 使用高阶函数将一个整数加倍 func double(n int) int { return n * 2 } // 使用高阶函数将两个整数相加 func add(a, b int) int { return a + b } func main() { // 使用闭包函数创建一个计数器 c := counter() // 调用计数器函数,并打印结果 fmt.Println(c()) // 输出: 1 fmt.Println(c()) // 输出: 2 // 使用高阶函数将整数加倍,并打印结果 fmt.Println(double(5)) // 输出: 10 // 使用高阶函数将两个整数相加,并打印结果 fmt.Println(add(3, 4)) // 输出: 7 } ``` 在上面的示例中,`counter`函数返回了一个闭包函数,用于实现简单的计数器。`double`函数和`add`函数都是高阶函数,可以作为参数传递给其他函数使用。这些示例展示了Go语言闭包函数和函数式编程的一些用法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值