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”模式使打印输出代码也“函数化”。