使用函数变量的好处:与外部函数共享数据,相比分成几个独立函数,减少数据参数的传递。
函数变量的递归调用
例子:根据先决条件规则,对数据进行排序(有向无环图的排序)
package main
import "fmt"
func main() {
var prereqs map[string][]string
prereqs = map[string][]string{
"a":{"b", "c"},
"d":{"e"},
"c":{"d"},
}
for i, course := range topoSort(prereqs) {
fmt.Printf("%d:\t%s\n", i+1, course)
}
}
func topoSort(m map[string][]string) []string {
var order []string
var seen = make(map[string]bool)
var visitAll func(item string) // 匿名函数需要进行递归时,必须先赋值给一个声明的变量
visitAll = func(item string) {
if !seen[item] {
seen[item] = true
//_, ok := m[item]
//if ok {
// for _, i := range m[item] {
// visitAll(i)
// }
// 不用判断m[item]是否存在,因为如果键名item不存在,m[item]为[]string的零值,为nil,visitAll函数中的循环不执行。
for _, i := range m[item] {
visitAll(i)
}
order = append(order, item)
}
}
// 字典中存放顺序无序,先把键值放到列表中,否则每次执行结果可能不一致
var keys []string
for key := range m {
keys = append(keys, key)
}
for _, k := range keys {
visitAll(k)
}
return order
}
匿名函数需要进行递归时,必须先赋值给一个声明的变量,合成一个声明,函数字面量将不能存在于visitAll变量的作用于中
visitAll := func(item string) {
visitAll(i) // 编译错误:undefined: visitAll
}