1、函数式编程
函数和闭包,go语言对函数式编程主要体现在闭包的能力
//累加器函数
func adder () func (value int) int {
sum := 0
return func(value int) int {
sum += value
return sum
} //返回的是闭包
}
func main(){
adder := adder()
for i:= 0 ; i< 10;i++{
fmt.Println(adder(i))
}
}
//0+1+...+i
函数式编程VS函数指针:
函数是一等公民:参数,变量,返回值都可以是函数(C++函数只是指针)
高阶函数
函数->闭包
”正统“函数式编程:(数学味道太浓)
不可变性:不能有状态,只有常量和函数
函数只能有一个参数
闭包:
函数体:
局部变量
自由变量(sum)连接其他变量
//不能有状态,正统函数
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(){
adder := adder2(0)
for i:= 0 ; i< 10;i++{
var s int
s,a = adder(i)
fmt.Println(adder(i),s)
}
}
//pthon中的闭包
def adder():
sum=0
def f(value):
nonlocal sum //需要生命
sum += value
return sum
return f
//python原生支持闭包
//使用__closure__来查看闭包内容
//c++中的闭包 C++14才编译通过
auto adder(){
auto sum =0 ;
return [=] (int value) mutable {
sum += value;
return sum;
};
}
//过去:stl或者boost带有类似库 //模拟闭包
//C++11及以后:支持闭包
//java中的闭包:
function<Integer,Integer> adder(){
final Holder <Integer> sum = new Holder<>(0);
return (Integer value) -> {
sum.value += value;
return sum.value;
};
}
sum不能改变,sum.value可以改变
1.8以后:使用Function接口和Lamba表达式来创建函数对象
匿名类或Lamba表达式均支持闭包
go闭包的应用:斐波那契数列
//a,b
// a,b
func fibonacci() func() int {
a,b := 0,1
return func() int {
a,b = b,a+b
return a
}
}
func main(){
f := fibonacci()
f() //1
f() //1
f() //2
f() //3
f() //5
f() //8
f() //13
f() //21
}
//go闭包的应用 :为函数实现接口
//使用生成器
func fibonacci() 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){ //函数也可以实现接口,函数是一等公民,也可以作为接收者
next := g()
if next > 1000{
return 0,io.EOF //大于10000文件读到头
}
s := fmt.Sprintf("%d\n",next) //用string来代理Read,因为其已经实现了这个接口
// TODO : incorrect if p is too small!
return strings.NewReader(s).Read(p) //这样函数就实现了Read接口
}
//go闭包的应用 :使用函数来遍历二叉树
func (node *Node) Traverse(){
node.TraverseFunc(func(node *Node){
node.Print()
})
fmt.Println()
}
func (node *Node) TraverseFunc (f func(*Node)){
if node == nil {
return
}
node.Left.TraverseFunc(f)
f(node)
node.Right.TraverseFunc(f)
}
//数一数函数有多少值
nodeCount := 0
root.TraverseFunc(func(node *tree.Node){
nodeCount++
})
fmt.Println("Node count:",nodeCount)
go语言闭包:
更为自然,不需要修饰如何访问自由变量
没有Lamba表达式,但是有匿名函数