(译)Go|(译)Go 语言中的闭包

【(译)Go|(译)Go 语言中的闭包】原文链接:Special Memory Powers of Go Closures
通常 Go 语言中的命名函数只能在包级别定义,但是为了方便广大 Gopher,Go 语言允许 function literal 在任何表达式中表示一个函数。
那么 function literal 是什么呢?它就是没有名字的函数体。这些匿名函数与 JavaScript 领域内的函数是一样的。
  • (译)Go|(译)Go 语言中的闭包
    文章图片
    image.png
这些函数可以访问整个作用域,所以最内层的函数可以访问包裹它的函数中的变量。
  • (译)Go|(译)Go 语言中的闭包
    文章图片
    image.png
从截屏中可以看到 appendArray() 是一个返回值类型为 func() []int 的函数,一个 appendArray() 调用将创建一个本地变量 x 与 y 并返回匿名函数,每次执行它都将 x 加 1,然后将 x 追加到 slice y 中。第二个 appendArray() 调用创建了第二个本地变量 x 与 y ,它自增这个本地变量并且返回指定函数。
这与 Go 的预言正好相符:函数是引用类型,函数的值是不可以进行比较的。
匿名函数是可以保存它们局部变量状态的,并且还可以访问或更改包裹它的函数的局部变量。
保存变量状态这个属性有助于我们解决很多计算机科学中的问题,例如:拓扑排序一下一个全栈开发工程师的技能树
//topological sortpackage mainimport ( "fmt" "sort" )var pathOfFullstack = map[string][]string{ "fullstack developer": {"C#", "Python", "Go", "Angular", "React"}, "C#":{"C"}, "Angular": {"html", "Css", "Javascript"}, "Go":{"C#", "Python"}, "React":{"html", "Javascript", "JSX"}, }func main() { for i, path := range topoSort(pathOfFullstack) { fmt.Printf("%d:\t%s\n", i+1, path) } }func topoSort(m map[string][]string) []string { var pathOrder []string visited := make(map[string]bool) var visitAll func(items []string) visitAll = func(items []string) { for _, item := range items { if !visited[item] { visited[item] = true visitAll(m[item]) pathOrder = append(pathOrder, item) } } } var paths []string for devPath := range m { paths = append(paths, devPath) } sort.Strings(paths) visitAll(paths) return pathOrder }// Output /* 1:html 2:Css 3:Javascript 4:Angular 5:C 6:C# 7:Python 8:Go 9:JSX 10: React 11: fullstack developer */

所以下一次你定义 API,就可以施展一下你自己的 Go 语言闭包了。

    推荐阅读