“有意思”系列将会分享平时遇到的好玩的东西,不限于代码。

函数值

Go的函数也是值,可以像其他值一样进行传递。换句话说,就像int,string一样,可以用作函数的参数或者返回值。
来设计一个有意思的函数,假设我们要对两个数字3,4进行处理,比如对它们进行求和,求差,求积,就可以先定义一个模板函数deal,它接受一个处理函数作为参数,返回值就是处理完的结果:

func deal(fn func(n1, n2 int) int) int {
	return fn(3, 4)
}

再定义一些处理函数:

func main() {
	multiply := func(n1, n2 int) int { return n1 * n2 }
	sum := func(n1, n2 int) int { return n1 + n2 }
	differ := func(n1, n2 int) int { return n1 - n2 }
	fmt.Println("两数乘积: ", deal(multiply))
	fmt.Println("两数之和: ", deal(sum))
	fmt.Println("两数之差: ", deal(differ))
}

multiply变量的值为乘法函数,接受n1,n2两个参数,返回n1和n2的积。同理,sum为两数之和的处理函数,differ为两数之差的处理函数。最后deal接受不同的处理函数作为入参,对3,4进行处理。结果如下
两数乘积: 12
两数之和: 7
两数之差: -1

函数的闭包

Go函数可以是一个闭包。闭包是一个函数值,它引用了其函数体之外的变量。该函数可以访问并赋予其引用的变量的值,换句话说,该函数被这些变量绑定在一起
比如我们要计算1 + 2 + 3 + ··· + n的值,除了公式法,让我们用函数闭包来做,首先定一个一个返回值是函数的函数:

func adder() func(int) int {
	sum := 0
	return func(i int) int {
		sum += i
		return sum
	}
}

当 n = 100时:

func main() {
	compute := adder()
	for i := 0; i <= 100; i++ {
		fmt.Println(compute(i))
	}
}

最后,结果为5050.

斐波那契闭包

通常斐波那契函数0, 1, 1, 2, 3, 5,···可以用递归或者公式法做,那么如果是函数闭包呢?我们可以设计一个函数,每次调用返回一个数,第一次返回0,第二次返回1,第三次返回1,第四次返回2...没错,闭包就可以做这个事。

func fibonacci() func() int {
	n1 := -1
	n2 := 1
	return func() int {
		n1, n2 = n2, n1+n2
		return n2
	}
}

fibonacci()返回一个函数,该函数的值是返回经过计算的内部初始值的n2。运行一下:

func main() {
	f := fibonacci()
	for i := 0; i < 10; i++ {
		fmt.Println(f())
	}
}

运行结果0, 1, 1, 2, 3, 5, 8, 13, 21, 34

参考资料
A Tour of Go