09、Golang 教程 - 函数式编程

函数式编程

  • 函数是一等公民:参数,变量,返回值都可以是函数

闭包

  • 闭包 = 匿名函数 + 自由变量的引用
     


func adder() func(value int) int {

    sum := 0 // 自由变量
    // 函数返回的时候不只是返回一个函数,而是返回一个闭包 包括自由变量和局部变量
    return func(value int) int {

      // value 局部变量
        sum += value
        return sum 
    }
}
func main() {

    adder := adder() // 闭包
    for i := 0; i < 10; i++ {

        fmt.Println(adder(i))
    }
    //0
    //1
    //3
    //6
    //10
    //15
    //21
    //28
    //36
    //45
}

例子

  • 斐波那契数列
 package main

func fibonacci() func() int {

    a, b := 0, 1
    return func() int {

        a, b = b, a+b
        return a
    }
}
func main() {

    f := fibonacci()
    println(f()) //1
    println(f()) //1
    println(f()) //2
    println(f()) //3
    println(f()) //5

}
  • 斐波那契数列2
 func fibonacci() intGen {

    a, b := 0, 1
    return func() int {

        a, b = b, a+b
        return a
    }
}

// 给函数实现接口,在go语言中 只要是类型,就可以实现接口
type intGen func() int

// 让函数实现Read接口
func (g intGen) Read(p []byte) (n int, err error) {

    next := g()
    s := fmt.Sprintf("%d\n", next)
    if next > 200 {

        return 0, io.EOF
    }
    return strings.NewReader(s).Read(p) //找个代理帮助我们读取
}

func printFileContents(reader io.Reader) {

    scanner := bufio.NewScanner(reader)
    for scanner.Scan() {

        fmt.Println(scanner.Text())
    }
}
func main() {

    f := fibonacci()
    printFileContents(f)//因为函数实现了Reader接口,所以就可以作为参数传入
    //1
    //1
    //2
    //3
    //5
    //8
    //13
    //21
    //34
    //55
    //89
    //144
}
  • 遍历二叉树
 // 传入一个函数 这样就可以对遍历过程中的节点做任意的事情
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(n *Node) {

    nodeCount++
})
fmt.Println(nodeCount)
  • Go语言没有Lambda表达式,只有匿名函数