58.笔记go语言——函数式编程

使用函数式编程使代码更抽象和更容易理解

先看个例子如下:

packagemain

 

import(

    "fmt"

)

 

typeStudentstruct{

    Name   string

    Age    int

    Heightint

}

 

funcmain(){

    Students:=[]*Student{

        &Student{"Danny",15,165},

        &Student{"Jacky",16,180},

        &Student{"Alan",17,172},

        &Student{"Sandy",18,168},

    }

    result1:=[]*Student{}

    for_,s:=rangeStudents{

        ifs.Age>16{

            result1=append(result1,s)

        }

    }

    fmt.Println("result1")

    for_,s:=rangeresult1{

        fmt.Println(s.Name)

    }

    result2:=[]*Student{}

    for_,s:=rangeStudents{

        if(s.Age>15)&&(s.Height>170){

            result2=append(result2,s)

        }

    }

    fmt.Println("result2")

    for_,s:=rangeresult2{

        fmt.Println(s.Name)

    }

}

执行如下:

result1

Alan

Sandy

result2

Jacky

Alan

使用函数式编程来替换,先创建一个filter函数如下:

func Filter(l []*Student, f func(*Student) bool) []*Student {

    result := []*Student{}

    for _, s := range l {

        if f(s) {

            result = append(result, s)

        }

    }

    return result

}

这是一个通用的Filter函数,传入列表l和一个函数f,对列表的每个成员调用传入的函数,如果函数f返回true,就把成员添加到结果列表中。

函数式编程中,把函数作为参数(也就是“函数作为值”),就可以把列表的便利操作给抽象了。接下去你可以专注思考如何实现f这个函数。

作为一个通用的Filter函数,它的第二个参数f只能接收列表的成员(在这个例子中,类型是*Student)这一个参数,问题1里面的另一个参数“16”,怎么传给我们要实现的函数f,这就需要用到“闭包”,我们先来看实现代码。

func AgeGreatThanFunc(age int) func(*Student) bool {

    return func(s *Student) bool {

        return s.Age > age

    }

}

创建一个函数AgeGreatThan,输入参数是一个希望和Student对象去比较的年龄值,返回是一个函数。这个函数可以用在Filter中,所以返回的这个函数的输入必须是*Student,输出必须是bool。这也是结果导向的思维方式。这个函数做的事情,就是拿Student对象的年龄和age比较,对了,返回的那个函数可以访问到传入的age参数,所以闭包是用来解决变量的作用域的问题的。当你需要得到一个函数,只接收一个参数,而实际使用中需要多个参数的时候,就像上面这样使用闭包,而参数减少的过程,称为“currying”。

同样道理,我们来实现问题2:获得 Age> 15 且 Height > 170的student列表

func ComplexFunc(age int, height int) func(*Student) bool {

    return func(s *Student) bool {

        return (s.Age > age) && (s.Height > height)

    }

}

然后修改代码如下:

packagemain
 
import(
    "fmt"
)
 
typeStudentstruct{
    Name   string
    Age    int
    Heightint
}
 
funcFilter(l[]*Student,ffunc(*Student)bool)[]*Student{
    result:=[]*Student{}
    for_,s:=rangel{
        iff(s){
            result=append(result,s)
        }
    }
    returnresult
}
 
funcComplexFunc(ageint,heightint)func(*Student)bool{
    returnfunc(s*Student)bool{
        return(s.Age>age)&&(s.Height>height)
    }
}
funcAgeGreatThanFunc(ageint)func(*Student)bool{
    returnfunc(s*Student)bool{
        returns.Age>age
    }
}
 
funcmain(){
    Students:=[]*Student{
        &Student{"Danny",15,165},
        &Student{"Jacky",16,180},
        &Student{"Alan",17,172},
        &Student{"Sandy",18,168},
    }
    result1:=Filter(Students,AgeGreatThanFunc(16))
    fmt.Println("result1")
    for_,s:=rangeresult1{
        fmt.Println(s.Name)
    }
    result2:=Filter(Students,ComplexFunc(15,170))
    fmt.Println("result2")
    for_,s:=rangeresult2{
        fmt.Println(s.Name)
    }
}

执行效果等同。

代码中Filter函数的第二个参数,是一个函数。你还可以使用“map”模式使打印输出代码也“函数化”。