函数式编程特点 参数 变量 返回值 都可以是函数
"正统"函数式编程特点如下
.不可变性:不能有状态,只有常量和函数
.函数只能有一个参数
但go语言区别于“正统”函数式编程 go语言是面向大众的语言 所以不会在语法上纠结正统不正统
下面先看一个函数式编程 闭包 的例子
package main
import "fmt"
func Adder() func(v int) int{ //闭包 返回值为匿名函数
sum := 0 //自由变量 自由变量我的理解是此函数内有效的不被回收的值
return func(v int)int{ //返回值为函数 完成闭包流程
sum += v //sum为叠加 不会被释放
return sum
}
}
func main(){
a := Adder() //将函数作为变量赋值给a是函数式编程的特点
for i:= 0; i < 10; i++{
fmt.Println(a(i)) //打印闭包返回值 i值实际是向Adder()的匿名函数赋值
}
}
比较一下正统的函数式编程
type IAdder func(int) (int , IAdder)
func adder2(base int) IAdder{
return func(v int) (int, IAdder) {
return base +v, adder2(base +v )
}
}
func main(){
a := adder2(0)
for i:= 0; i < 10; i++{
var s int
s, a = a(i)
fmt.Println(s)
}
}
区别是不是很大
下面再举一个例子
package main
import "fmt"
func fibonacco()func () int{
a, b:= 0,1
return func()int{
a,b = b, a+b
return a
}
}
func main(){
a := fibonacco()
for i:=0; i< 10; i++ {
fmt.Println(a())
}
}
这是典型的斐波那契算法 用go语言实现显得很简洁
下面是用函数作为类型 定义接口 进行函数运算
package main
import (
"fmt"
"io"
"bufio"
"strings"
)
func fibonacco()intGen{
a, b:= 0,1
return func() int{
a,b = b, a+b
return a
}
}
type intGen func() int //将函数定义为类型
func (g intGen)Read(p []byte) (n int, err error){ //定义接口 go语言中任何类型都可以实现接口 函数只是一个特殊的参数
next := g() //next是 类型传输值
if next > 10000{ //限制无限循环
return 0,io.EOF
}
s := fmt.Sprintf("%d\n",next) //将整形转化为字符串 strings.NewReader使用
return strings.NewReader(s).Read(p) //使用s做打印 p为uint8可使用位数
}
func printFileContents(reader io.Reader){ //打印任何类型
scanner := bufio.NewScanner(reader) //将函数转换 赋值给scanner
for scanner.Scan() { //将scanner里面的值全部循环打印出来
fmt.Println(scanner.Text())
}
}
func main(){
a := fibonacco()
printFileContents(a)
}
由上可得出 go语言中 函数式编程可用函数作为类型 将函数类型传递到函数里面直接可以使用
下面再来一个例子
package tree
import "fmt"
type Node struct{ //二叉树
Value int
Left,Right *Node
}
func CreateNode(r int) *Node{
return &Node{r,nil,nil}
}
func (node *Node)SetValue(v int){
node.Value = v
}
func (node *Node)printf(){
fmt.Println(node.Value)
}
func (node *Node)Traverse(){ //需要注意的地方在这
node.TraverseFunc(func (n *Node){ //函数做参数传递 明确的表现出函数式编程
n.printf() //n值由递归不断赋值 每次打印内容不相同
})
}
func (node *Node)TraverseFunc(f func(*Node)){ //需要注意的地方在这 函数做参数传递 并且有形参f
if node == nil{
return
}
node.Left.TraverseFunc(f) //递归 同时传递f 我的理解是f值在递归返回之前 值不发生变化
f(node) //f开始运作 f作为函数形参 并且函数为指针 node参数放入f中_
//上方n形参指向地址改变 做出打印内容
node.Right.TraverseFunc(f) //中序遍历 结束后打印剩余数据
}
package main
import "awesomeProject1/test/shu/tree"
func main(){
root := tree.Node{3,nil,nil} //普通的二叉树赋值
root.Left = &tree.Node{}
root.Right = &tree.Node{Value:5}
root.Right.Left = new(tree.Node)
root.Left.Right = tree.CreateNode(2)
root.Right.Left.SetValue(4)
root.Traverse()
}
总结go语言的函数式编程
.更为自然 不需要修饰如何访问自由变量
.没有lambda 但是具有匿名函数
.go语言闭包("函数式编程")个人认为是go语言的难点也是重点