网站内容优化,贵阳做网站软件,做网站的人还能做什么,学网站建设好吗什么是第一类函数#xff1f;
支持第一类函数的语言允许将函数分配给变量#xff0c;作为参数传递给其他函数#xff0c;并从其他函数返回。Go 支持第一类函数。
在本教程中#xff0c;我们将讨论第一类函数的语法和各种用例。
匿名函数
让我们从一个简单的例子开始
支持第一类函数的语言允许将函数分配给变量作为参数传递给其他函数并从其他函数返回。Go 支持第一类函数。
在本教程中我们将讨论第一类函数的语法和各种用例。
匿名函数
让我们从一个简单的例子开始它为变量分配一个函数。
package mainimport (fmt
)func main() {a : func() {fmt.Println(hello world first class function)}a()fmt.Printf(%T, a)
}Run in playground
在上面的程序中我们为第 8 行中的变量分配了一个函数。这是将函数分配给变量的语法。如果您仔细观察分配的函数没有名称。**这些类型的函数称为匿名函数因为它们没有名称。
调用此函数的唯一方法是使用变量 。我们在下一行中已经完成了此操作。 调用该函数我们打印变量的类型。
运行此程序将打印
hello world first class function
func()也可以调用匿名函数而不将其分配给变量。让我们看看在下面的示例中是如何完成的。
package mainimport (fmt
)func main() {func() {fmt.Println(hello world first class function)}()
}
Run in playground
在上面的程序中在第 8 行中定义了一个匿名函数在函数定义之后我们立即在第 10 行中调用该函数。该程序将输出
hello world first class functionIt is also possible to pass arguments to anonymous functions just like any other function. 1package main23import (4 fmt5)67func main() {8 func(n string) {9 fmt.Println(Welcome, n)
10 }(Gophers)
11}GO
Run in playground
在上面的程序中将一个字符串参数传递给第一行的匿名函数。运行这个程序将打印
Welcome Gophers用户自定义函数类型
就像定义自己的结构类型一样也可以定义自己的函数类型。
type add func(a int, b int) int创建了一个新的函数类型它接受两个整数参数并返回一个整数。
让我们编写一个程序
package mainimport (fmt
)type add func(a int, b int) intfunc main() {var a add func(a int, b int) int {return a b}s : a(5, 6)fmt.Println(Sum, s)
}
Run in playground
在上面的程序中第10行定义一个类型的变量并给它赋值一个签名与该类型匹配的函数。我们在第13行调用这个函数。并将结果赋值给s。这个程序将打印
Sum 11高阶函数
高阶函数的定义是一个至少完成以下一项的函数
接受一个或多个函数作为参数返回一个函数作为结果
让我们看一下上面两个场景的一些简单示例。
将函数作为参数传递给其他函数
package mainimport (fmt
)func simple(a func(a, b int) int) {fmt.Println(a(60, 7))
}func main() {f : func(a, b int) int {return a bsimple(f)
}
Run in playground
在上面的例子中在第 7 行中我们定义了一个simple函数该函数接受一个接受两个 int 参数并返回一个 int 作为参数的函数。在第 12 行的 main 函数中我们创建一个匿名函数f其签名与函数的参数匹配simple。我们在下一行中调用并作为参数传递给它。此程序打印为输出。
67现在让我们重写上面的程序并从simple函数中返回一个函数。
package mainimport (fmt
)func simple() func(a, b int) int {f : func(a, b int) int {return a b}return f
}func main() {s : simple()fmt.Println(s(60, 7))
}
Run in playground
在上面的程序中第 7 行中的简单函数返回一个函数该函数接受两个参数并返回一个参数。
这个简单的函数是从第 15 行调用的。simple 的返回值分配给s 。现在s包含 function 返回的函数simple。我们s在第 1 6行调用并传递两个 int 参数。该程序输出67。
闭包
闭包是匿名函数的一种特殊情况。闭包是访问函数体外部定义的变量的匿名函数。
举个例子会让事情变得更清楚。
package mainimport (fmt
)func main() {a : 5func() {fmt.Println(a , a)}()
}
Run in playground
在上面的程序中匿名函数访问第 10 行中存在于其主体外部的变量a。因此这个匿名函数是一个闭包。
每个闭包都绑定到其自己的周围变量。让我们通过一个简单的例子来理解这意味着什么。
package mainimport (fmt
)func appendStr() func(string) string {t : Helloc : func(b string) string {t t breturn t}return c
}func main() {a : appendStr()b : appendStr()fmt.Println(a(World))fmt.Println(b(Everyone))fmt.Println(a(Gopher))fmt.Println(b(!))
}
Run in playground
在上面的程序中函数appendStr返回一个闭包。该闭包绑定到变量t。让我们来理解这意味着什么。
变量a和b在17, 18行号中声明。 是闭包它们与自己的值 绑定t。
我们首先a使用World参数进行调用。a现在的版本的值t变为Hello World。
在20 行号中。我们b用Everyone参数调用。由于b绑定到它自己的变量t因此 b的版本再次t具有初始值Hello。因此在此函数调用之后 t 的版本的值变为Hello Everyone。该程序的其余部分是不言自明的。
该程序将打印
Hello World
Hello Everyone
Hello World Gopher
Hello Everyone !一类函数的实际应用
到目前为止我们已经定义了什么是第一类函数并且我们已经看到了一些人为的例子来了解它们是如何工作的。现在让我们编写一个具体的程序来展示第一类函数的实际用法。
我们将创建一个程序根据某些标准过滤一部分学生。让我们一步一步地解决这个问题。
首先让我们定义学生类型。
type student struct {firstName stringlastName stringgrade stringcountry string
}
下一步是编写函数filter。该函数采用一部分学生和一个确定学生是否符合过滤条件的函数作为参数。一旦我们编写了这个函数我们就会更好地理解。让我们继续去做吧。
func filter(s []student, f func(student) bool) []student {var r []studentfor _, v : range s {if f(v) true {r append(r, v)}}return r
}
在上面的filter函数中第二个参数是一个以student作为参数并返回的函数bool。此函数确定特定学生是否符合条件。第 3 行我们循环的学生切片。我们将每个学生作为参数传递给函数f。如果返回true则意味着该学生已通过过滤条件并且他被添加到切片中r。你可能对这个函数的实际用途有点困惑但是一旦我们完成程序就会清楚了。我已经添加了主要功能并在下面提供了完整的程序。
package mainimport (fmt
)type student struct {firstName stringlastName stringgrade stringcountry string
}func filter(s []student, f func(student) bool) []student {var r []studentfor _, v : range s {if f(v) true {r append(r, v)}}return r
}func main() {s1 : student{firstName: Naveen,lastName: Ramanathan,grade: A,country: India,}s2 : student{firstName: Samuel,lastName: Johnson,grade: B,country: USA,}s : []student{s1, s2}f : filter(s, func(s student) bool {if s.grade B {return true}return false})fmt.Println(f)
}
Run in playground
main 函数中我们首先创建两个学生s1并将s2他们添加到 slice 中s。现在假设我们想要找出所有有 Grade 的学生B。我们在上面的程序中通过传递一个函数来建立这一点该函数检查学生是否有成绩B如果有则返回 true。上面的程序将打印
[{Samuel Johnson B USA}]假设我们想找到所有来自印度的学生。通过将函数参数更改为过滤器函数可以轻松完成此操作。 我在下面提供了执行此操作的代码
c : filter(s, func(s student) bool {if s.country India {return true}return false
})
fmt.Println(c)
请将其添加到 main 函数并检查输出。
让我们再编写一个程序来结束本节。该程序将对切片的每个元素执行相同的操作并返回结果。例如如果我们想要将切片中的所有整数乘以 5 并返回输出则可以使用一等函数轻松完成。这些对集合中的每个元素进行操作的函数称为map函数。我提供了下面的程序。这是不言自明的。
package mainimport (fmt
)func iMap(s []int, f func(int) int) []int {var r []intfor _, v : range s {r append(r, f(v))}return r
}
func main() {a : []int{5, 6, 7, 8, 9}r : iMap(a, func(n int) int {return n * 5})fmt.Println(r)
}
Run in playground
上面的程序会打印
[25 30 35 40 45]