go 的函数式编程

在 go 语言中,函数是一等公民。函数既可以作为参数传入,也可以作为返回值返回。
go 语言的函数式编程最典型的例子就是 闭包。

闭包是什么呢?

简单讲,闭包就是指有权访问另一个函数作用域中的变量的函数。
它由两部分构成:函数,以及创建该函数的环境。环境由闭包创建时在作用域中的任何局部变量组成。
外部函数调用之后其变量对象本应该被销毁,但闭包的存在使我们仍然可以访问外部函数的变量对象,这就是闭包的重要概念。

闭包

package main

import "fmt"

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

func main() {
    f := fib()
    for i := 0 ; i < 20;i++ {
        fmt.Printf("%d ",f())
    }
}
// 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946
为函数生成接口

上面的例子中,f() 是每执行一遍的话 ,会生成一个新的斐波那契数。可以把他实现成为一个read的接口。那么就可以使用 scanner.Scan()。像读文件一样打印斐波那契数列。

package main

import (
    "bufio"
    "fmt"
    "io"
    "strings"
)

func fib() IntGen {
    a,b := 0,1
    return func() int {
        b,a = a+b,b
        return b
    }
}

type IntGen func() int

func (g IntGen) Read(p []byte) (n int,err error) {
    next := g()
    if next > 1000000 {
        return 0,io.EOF
    }
    s := fmt.Sprintf("%d ",next)
    return strings.NewReader(s).Read(p)
}

func PrintFib(read io.Reader) {
    scanner := bufio.NewScanner(read)

    for scanner.Scan() {
        fmt.Println(scanner.Text())
    }
}
func main() {
    f := fib()
    PrintFib(f)
} 
传入函数来解决问题

假设现在有一个遍历二叉数的函数。他只是做了打印的操作,那能否使用之前的所学到的知识,再丰富其功能呢。

func (t *TreeNode) Traverse() {
    if t == nil {
        return
    }

    t.Left.Traverse()
    fmt.Println(t.Val)
    t.Right.Traverse()
}

用闭包改造后,不仅可以打印出每一个值,而且可以打印出一共有多少个节点。

func (t *TreeNode) Traverse() {
    cnt := 0
    t.TraverseFunc(func(node *TreeNode) {
        fmt.Printf("%d ",node.Val)
        cnt ++
    })
    fmt.Println("\nNode cnt is",cnt)
}

func (t *TreeNode) TraverseFunc(f func (*TreeNode) ) {
    if t == nil {
        return
    }

    t.Left.TraverseFunc(f)
    f(t)
    t.Right.TraverseFunc(f)
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  •   函数表达式是 JavaScript 中的一个既强大有容易令人困惑的特性。定义函数的的方式有两种: 函数声明; ...
    霜天晓阅读 839评论 0 1
  • 这是16年5月份编辑的一份比较杂乱适合自己观看的学习记录文档,今天18年5月份再次想写文章,发现简书还为我保存起的...
    Jenaral阅读 2,899评论 2 9
  • 1 概述 1.1函数的声明 JavaScript 有三种声明函数的方法。 (1)function 命令 funct...
    徵羽kid阅读 422评论 0 1
  • 函数是一段可以反复调用的代码块。函数还能接受输入的参数,不同的参数会返回不同的值。 概述 函数的声明 JavaSc...
    oWSQo阅读 1,322评论 0 4
  • 函数是一段可以反复调用的代码块。函数还能接受输入的参数,不同的参数会返回不同的值。 概述 函数的声明 JavaSc...
    许先生__阅读 452评论 0 1