关于golang的函数式编程

函数式编程特点 参数 变量 返回值 都可以是函数

"正统"函数式编程特点如下

.不可变性:不能有状态,只有常量和函数

.函数只能有一个参数

但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语言的难点也是重点

猜你喜欢

转载自blog.csdn.net/weixin_42654444/article/details/82146033
今日推荐