爱上开源之golang入门至实战第四章函数(Func)(七)
在go语言里,func本质上是一个类型关键字。 使用func来进行声明,本质上就是什么了一个func的对象。 对象名为function_name, 这个对象的类型是func。 所以在golang语言里, 在访问范围的允许情况下, 函数可以作为一个对象进行访问或者赋值给另外一个变量; 或者函数也可以作为其它函数的参数进行传递,然后在其它函数内调用执行; 就和Javascript里的callback函数一样;这个文章就来谈谈,函数作为参数在Go语言里的调用。

先来看看一个例子:
- func PrintFibonacci(n int, fibonacciWorker func(num int) []int) {
- if fibonacciWorker == nil {
- panic("Not assign worker")
- }
-
- result := fibonacciWorker(n)
-
- fmt.Printf("Fibonacci(%d)=%v \n", n, result)
- }
- func FibonacciWorker(a int) (n []int) {
- if a <= 0 {
- n = append(n, 0)
- return
- }
- if a == 1 {
- n = append(FibonacciC(a-1), 1)
- return
- }
-
- n = append(FibonacciC(a - 1))
- n = append(n, n[len(n)-1]+n[len(n)-2])
-
- return
- }
- PrintFibonacci(4, FibonacciWorker)
- PrintFibonacci(6, FibonacciWorker)
- PrintFibonacci(10, FibonacciWorker)
-
- ===== OUTPUT =====
- Fibonacci(4)=[0 1 1 2 3]
- Fibonacci(6)=[0 1 1 2 3 5 8]
- Fibonacci(10)=[0 1 1 2 3 5 8 13 21 34 55]
上述代码,
首先定义了PrintFibonacci函数,PrintFibonacci函数两个参数,
第一个参数是整数类型,传入调用的n值,
另一个参数fibonacciWorker是一个函数类型的参数;函数类型的参数是整数型类型,用来接收传入参数,返回一个整数类型的数组,
在PrintFibonacci函数里, 把接收到的整数类型n,作为参数传递到fibonacciWorker这个传入的函数类型,并执行fibonacciWorker函数,返回整数型类型的数组,
然后把返回值打印到控制台; 这样的Callback的实现模式,
可以实现一些Java设计模式里的效果。 把具体的实现实现在具体函数里, 定义好这种函数类型的传入参数,返回值,
然后把此类函数类型作为参数传入, 在外部调用时, 把具体的实现作为参数对这个方法进行调用,就可以达到实现和接口的隔离了。 函数也可以作为数组的元素, 把数组里的元素遍历再进行调用。
来看看下面的代码:
- type WordProcess func(input string) string
-
- func filter(source string, chains []WordProcess) string {
- for _, process := range chains {
- if process != nil {
- fmt.Printf("%q =>", source)
- source = process(source)
- fmt.Printf("%q\n", source)
- }
- }
- return source
- }
定义了一个WordProcess的函数类型, 传入参数字符串,返回字符串; WordProcess对传入的字符串进行字符处理。
在第二段,定义一个filter函数,函数传入source字符串,和一个WordProcess的函数数组; 函数数组都是进行字符处理的,遍历数组取到每个WordProcess函数,并依次进行处理,然后打印转换的过程,并返回结果。
下面我们来看看调用的代码
- func main() {
- toUpper := func(input string) string {
- return strings.ToUpper(input)
- }
-
- toTrim := func(input string) string {
- return strings.TrimSpace(input)
- }
-
- toTrimPrefix := func(input string) string {
-
- return strings.TrimPrefix(input, "AAA")
- }
-
- chains := append([]WordProcess(nil), toUpper, toTrim, toTrimPrefix)
-
- result := filter(" aaa hello ", chains)
- fmt.Printf("result = %v \n", result)
- }
-
-
- ===== OUTPUT =====
- " aaa hello " =>" AAA HELLO "
- " AAA HELLO " =>"AAA HELLO"
- "AAA HELLO" =>" HELLO"
- result = HELLO
这个调用段的过程;
先定义一个WordProcess的函数实现toUpper, 该实现对传入字符串进行转大写处理; 接着定义一个toTrim的函数,该函数实现对传入字符串进行去除空格处理, 最后定义一个toTrimPrefix的函数,将传入字符串前AAA字符串进行出除。
然后通过Append函数,将三个预先定义好的WordProcess函数对象加入到chains数组里,
最后传入字符串" aaa hello "进行filter调用, 通过filter依次调用,最后的结果就是HELLO了。
通过这样的方式,可以实现一些设计模式,特别是应用系统设计里,经常就有类似的代码可以发现。http里提供路由的功能就是使用类似以上的代码进行实现的。
