Go语言圣经-匿名函数1.拥有函数名的函数只能在包级语法块中被声明,通过函数字面量(function literal),我们可绕过这一限制,在任何表达式中表示一个函数值2.通过这种方式定义的函数可以访问完整的词法环境(lexical environment),这意味着在函数中定义的内部函数可以引用该函数的变量3.函数值不仅仅是一串代码,还记录了状态,意味着匿名函数和父函数中,存在变量引用,函数值属于引用类型和函数值不可比较的原因。Go使用闭包(closures)技术实现函数值,Go程序员也把函数值叫做闭包4.给定一些计算机课程,每个课程都有前置课程,只有完成了前置课程才可以开始当前课程的学习,这类问题被称作拓扑排序。从概念上说,前置条件可以构成有向图。
练习5.10: 重写topoSort函数,用map代替切片并移除对key的排序代码。验证结果的正确性(结果不唯一)。
练习5.11: 现在线性代数的老师把微积分设为了前置课程。完善topSort,使其能检测有向图中的环。
练习5.12: gopl.io/ch5/outline2(5.5节)的startElement和endElement共用了全局变量depth,将它们修改为匿名函数,使其共享outline中的局部变量。
<div class="cnblogs_Highlighter">
<pre class="brush:go;gutter:true;">package main
import (
"fmt"
"golang.org/x/net/html"
"net/http"
"sort"
)
var prereqs = map[string][]string{
"algorithms": {"data structures"},"calculus": {"linear algebra"},"compilers": {
"data structures","formal languages","computer organization",},"data structures": {"discrete math"},"databases": {"data structures"},"discrete math": {"intro to programming"},"formal languages": {"discrete math"},"networks": {"operating systems"},"operating systems": {"data structures","computer organization"},"programming languages": {"data structures",}
func main() {
for i,course := range topoSort(prereqs) {
fmt.Printf("%d:t%sn",i+1,course)
}
fmt.Println("------------------------")
for k,v := range topoSort2(prereqs) {
fmt.Printf("%d:t%sn",k,v)
}
fmt.Println("------------------------")
outline("http://mail.sina.net")
}
/
练习5.10: 重写topoSort函数,用map代替切片并移除对key的排序代码。验证结果的正确性(结果不唯一)。
/
func topoSort2(m map[string][]string) map[int]string {
var order = make(map[int]string)
index := 1
seen := make(map[string]bool)
var visitAll func(items []string)
visitAll = func(items []string) {
for ,item := range items {
if !seen[item] {
seen[item] = true
visitAll(m[item])
order[index] = item
index++
}
}
}
var keys []string
for key := range m {
keys = append(keys,key)
}
visitAll(keys)
return order
}
func topoSort(m map[string][]string) []string {
var order []string
seen := make(map[string]bool)
var visitAll func(items []string)
visitAll = func(items []string) {
for ,item := range items {
if !seen[item] {
seen[item] = true
visitAll(m[item])
order = append(order,item)
}
}
}
var keys []string
for key := range m {
keys = append(keys,key)
}
sort.Strings(keys)
visitAll(keys)
return order
}
/
练习5.11: 现在线性代数的老师把微积分设为了前置课程。完善topSort,使其能检测有向图中的环。
等着去看数据结构再看这个题
/
/
练习5.12: gopl.io/ch5/outline2(5.5节)的startElement和endElement共用了全局变量depth,将它们修改为匿名函数,使其共享outline中的局部变量。
/
func outline(url string) (string,error) {
resp,err := http.Get(url)
if err != nil {
return "",err
}
doc,_ := html.Parse(resp.Body)
//使用匿名函数实现
var depth int
var startElement func(n html.Node)
var endElement func(n html.Node)
startElement = func(n *html.Node) {
if n.Type == html.ElementNode {
attr := ""
for _,a := range n.Attr {
attr += " " + a.Key + "=" + """ + a.Val + "" "
}
fmt.Printf("%*s<%s%s",depth*2,"",n.Data,attr)
depth++
}
if n.Type == html.ElementNode && n.FirstChild == nil && n.Data != "script" {
fmt.Printf("/>n")
} else if n.Type == html.ElementNode {
fmt.Printf(">n")
}
if n.Type == html.TextNode {
fmt.Printf("%*s %sn",n.Data)
}
}
endElement = func(n *html.Node) {
if n.Type == html.ElementNode && n.FirstChild == nil && n.Data != "script" {
depth--
fmt.Printf("n")
return
}
if n.Type == html.ElementNode {
depth--
fmt.Printf("%*s</%s>n",n.Data)
}
}
//1.使用函数值
forEachNode(doc,startElement,endElement)
resp.Body.Close()
return "",nil
}
func forEachNode(n html.Node,pre,post func(n html.Node)) {
//显式的调用一下
if pre != nil {
pre(n)
}
//fmt.Println(n.Data)
for c := n.FirstChild; c != nil; c = c.NextSibling {
forEachNode(c,post)
}
if post != nil {
post(n)
}
}
 (编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|