四时宝库

程序员的知识宝库

go语言函数式编程(go语言编程入门与实战技巧)

函数式编程

正统的函数式编程有两个要求:

  1. 不可变性:只能有常量和函数。
  2. 函数只能有一个参数

go语言中的函数式编程显然不是正统的函数式编程,因为go语言的函数大都包含了变量和多个参数。

函数式编程实现的前提条件

函数式编程顾名思义,以函数为中心进行编程,意味着函数可以当作变量进行赋值,可以当作另外一个函数的入参,可以作为返回值返回。综合起来,函数式编程要将函数视为一级对象。

go语言实现函数式编程

go语言通过闭包实现函数式编程,而闭包的价值在于可以作为函数对象或者匿名函数。闭包的概念为闭包是包含自由变量的代码块,自由变量指的是没有在代码块内定义,而是在定义代码块的环境中定义,因为这些代码块运行的时候引用了自由变量,因此自由变量不会被垃圾回收器回收,而是一直存在。

上代码解释:

package main

import "fmt"

func adder() func(int) int {
   sum := 0
   return func(i int) int {
      sum += i
      return sum
   }
}
func main() {
   add := adder()
   for i := 0; i < 10; i++ {
      fmt.Printf("0 + .... + %d: %d\n", i, add(i))
   }
}

首先定义adder()函数,adder()函数没有入参,返回体为一个匿名函数,这个匿名函数就是闭包。匿名函数传入局部变量i,同时拥有一个外部的sum,而这个sum就是自由变量,因为sum没有在匿名函数这个代码块内部被定义,而是在外部被定义,而这个外部就是定义代码块的环境,根据闭包的定义,这个匿名函数就是一个闭包,而返回的闭包内部除了具体的运输代码,局部变量i,还有就是自由变量sum,由于自由变量被闭包调用,因此当函数运行的时候,sum不会被回收,它会一直被累加,而产生的结果如下。

0 + .... + 0: 0
0 + .... + 1: 1
0 + .... + 2: 3
0 + .... + 3: 6
0 + .... + 4: 10
0 + .... + 5: 15
0 + .... + 6: 21
0 + .... + 7: 28
0 + .... + 8: 36
0 + .... + 9: 45

闭包的主体为函数体,函数体包含局部变量和自由变量,如果自由变量是结构的话,还包含结构连接的其它结构。

用自由变量sum进行累加,这当然非常灵活,但从正统的函数式编程来说,它显然不是,因为sum是一个变量,如果用变量来表示一个可变的状态的话,它就不是一个正统的函数式编程,正统的函数式编程只能是常量和函数,因此我们可以用函数来表示状态,实现累加的效果,代码如下:

type Addr func(int) (int, Addr)

func getResultAndState(v int) Addr {
   return func(i2 int) (i int, addr Addr) {
      return v + i2, getResultAndState(v + i2)
   }
}
func main() {
   add := getResultAndState(0)
   for i := 0; i < 10; i++ {
      var i2 int
      i2, add = add(i)
      fmt.Printf("0 + .... + %d: %d\n", i, i2)
   }
}

首先定义函数结构体,入参为int变量,返回值为其本身和结果,这样可以用该函数存储状态。定义函数getResultAndState,函数的返回值为闭包,这个闭包包含了结果和下一个状态函数。

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言
    友情链接