GO是函数式编程,不是面像对象的语言,它没有对象的概念,一切都是根据结构体去分配内存,GO中的函数也是如此。
先上一段代码:
package main
import "fmt"
func adder1() func(i int) int {
sum := 0
return func(v int) int {
sum += v
return sum
}
}
func main() {
//a := adder1()表达式应该是得到下面这个函数
//return func(v int) int {
// sum += v
// return sum
//}
a := adder1()
//每次往a函数中传入参数都会得到自加
//sum := 0 -> sum是个函数闭包内的自由变量
for i := 0;i<10 ;i++ {
fmt.Println(a(i))
}
}
代码中已经加了比较详细的注释,当a=adder1()时编译器会返回一个函数的闭包。
函数体部分是:
return func(v int) int {
sum += v
return sum
}
sum是函数体的自由变量,这个变量也可以是结构体,如果是结构体的话还可能会引用到外部的变量,会形成一棵引用树,最终都会被包括到函数的闭包中。
篇外话,正统的函数式编程是不可以有状态和变量了,当然就GO来说对此无要求。
按照函数式编程的定义,本段代码应该改成这个样子:
package main
import "fmt"
type iAdder func(i 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.Printf("0+1+...%d = %d\n",i,s)
}
}
这个函数中只有常量和函数体,是正统的函数式编程,当这个没有上面的代码好理解
再来一段复杂点的,让fibonacci数列实现Reader接口,以函数的方式来读取
package main
import (
"bufio"
"fmt"
"io"
"strings"
)
type intGen func() int
func (g intGen)Read(p []byte)(n int,err error) {
next := g()
if next > 1000 {
return 0,io.EOF
}
s := fmt.Sprintf("%d\n",next)
return strings.NewReader(s).Read(p)
}
func iAdder() intGen {
a,b := 0,1
return func() int {
a,b = b,a+b
return a
}
}
func printFileContens(reader io.Reader) {
scanner := bufio.NewScanner(reader)
for scanner.Scan(){
fmt.Println(scanner.Text())
}
}
func main() {
f := iAdder()
printFileContens(f)
}
没什么好说的,代码可直接运行,对着敲几遍就明白了