本文继上文 golang笔记06–golang 面向接口, 进一步了解 go语言的面向接口特性和相应注意事项。
具体包括 : 函数式编程、函数式编程案例一、函数式编程案例二 等内容。
2.1 函数式编程
go 语言的函数式编程主要体现在函数与闭包上面。
函数式编程 vs 函数指针:
函数是一等公民: 参数、变量、返回值都可以是函数;
高阶函数: 函数的参数也可以是函数;
函数 -> 闭包;
“正统” 函数式编程:
不可变性: 不能有状态,只有常量和函数;
函数只能有一个参数;
go 语言闭包的结构图如下所示:
package main
import "fmt"
func adder() func(int) int {
sum := 0
return func(v int) int {
sum += v
return sum
}
}
func main() {
a := adder()
for i := 0; i < 10; i++ {
fmt.Printf("0+ ... +%d=%d\n", i, a(i))
}
}
输出:
0+ ... +0=0
0+ ... +1=1
0+ ... +2=3
0+ ... +3=6
0+ ... +4=10
0+ ... +5=15
0+ ... +6=21
0+ ... +7=28
0+ ... +8=36
0+ ... +9=45
2.2 函数式编程案例一
通过函数式编程实现斐波那契数列,其表达式为:
F[n]=F[n-1]+F[n-2](n>=2,F[0]=0,F[1]=1)
以下案例输出10000 以内的斐波那契数列:
package main
import (
"bufio"
"fmt"
"io"
"strings"
)
func fibonacci() func() int {
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 > 10000 {
return 0, io.EOF
}
s := fmt.Sprintf("%d\n", next)
return strings.NewReader(s).Read(p)
}
func printFileContents(reader io.Reader) {
scanner := bufio.NewScanner(reader)
for scanner.Scan() {
fmt.Println(scanner.Text())
}
}
func main() {
var f intGen = fibonacci()
//fmt.Println(f())
//fmt.Println(f())
//fmt.Println(f())
//fmt.Println(f())
//fmt.Println(f())
//fmt.Println(f())
printFileContents(f)
}
输出:
1
1
2
3
5
......
4181
6765
2.3 函数式编程案例二
本案例中通过函数式编程来实现二叉树的中序(中根)遍历,对应 TraverseV2 函数。
chapter7/tree$ tree -L 2
.
├── entry
│ └── main.go
└── node.go
vim node.go
package tree
import "fmt"
type Node struct {
Value int
Left, Right *Node
}
func (node Node) Print() {
fmt.Print(node.Value, " ")
}
func (node *Node) SetValue(value int) {
if node == nil {
fmt.Println("Setting value to nil node, ignored")
return
}
node.Value = value
}
func CreateNode(value int) *Node {
return &Node{Value: value}
}
func (node *Node) Traverse() {
if node == nil {
return
}
node.Left.Traverse()
node.Print()
node.Right.Traverse()
}
func (node *Node) TraverseV2() {
node.TraverseFunc(func(nd *Node) {
nd.Print()
})
fmt.Println()
}
func (node *Node) TraverseFunc(f func(*Node)) {
if node == nil {
return
}
node.Left.TraverseFunc(f)
f(node)
node.Right.TraverseFunc(f)
}
vim main.go
package main
import (
"fmt"
"learngo/chapter7/tree"
)
func main() {
fmt.Println("this is chapter 7.3")
var root tree.Node
root = tree.Node{Value: 3}
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()
fmt.Println("\nthis func traverseV2")
root.TraverseV2()
nodeCount := 0
root.TraverseFunc(func(node *tree.Node) {
nodeCount++
})
fmt.Println("Node count:", nodeCount)
}
输出:
this is chapter 7.3
0 2 3 4 5
this func traverseV2
0 2 3 4 5
Node count: 5
3 注意事项
待添加
4 说明