funcmain() { for i, course := range topoSort(prereqs) { fmt.Printf("%d:\t%s\n", i+1, course) } } functopoSort(m map[string][]string) []string{ var order []string var keys []string for key := range m{ keys = append(keys,key) } visit := make(map[string] bool) // 匿名函数 // 匿名函数必须先声明再赋值 var visitALL func(keys []string) //深度遍历 visitALL = func(keys []string){ for _,key := range keys{ if !visit[key]{ visit[key] = true visitALL(m[key]) order = append(order,key) } } } visitALL(keys) return order }
doc, err := html.Parse(resp.Body) resp.Body.Close() if err != nil { returnnil, fmt.Errorf("parsing %s as HTML: %v", url, err) }
var links []string visitNode := func(n *html.Node) { if n.Type == html.ElementNode && n.Data == "a" { for _, a := range n.Attr { if a.Key != "href" { continue } if strings.Contains(a.Val,"http") ==false{ continue } link, err := resp.Request.URL.Parse(a.Val) if err != nil { continue// ignore bad URLs } links = append(links, link.String()) } } } forEachNode(doc, visitNode, nil) return links, nil }
funcforEachNode(n *html.Node, pre, post func(n *html.Node)) { if pre != nil { pre(n) } for c := n.FirstChild; c != nil; c = c.NextSibling { forEachNode(c, pre, post) } if post != nil { post(n) } } //封装Extract,输出URL funccrawl(url string) []string{ fmt.Println(url) list, err := Extract(url) if err!=nil{ log.Print(err) } return list } //层次遍历,对每个list元素调用f函数 //将返回内容添加到worklist中,对每个元素最多调用一次f函数 funcbFS(f func(item string) []string, list []string){ visit := make(map[string] bool) forlen(list)>0{ items := list list = nil for _, item := range items{ if !visit[item]{ visit[item] =true list = append(list,f(item)...) } } } }
funcmain(){ var urls []string urls = append(urls,"http://hao123.com") bFS(crawl, urls) }
``` ------------------------ ### 延迟调用和恢复 ```golang funcforEachNode(n *html.Node, pre, post func(n *html.Node)) { if pre != nil { pre(n) } for c := n.FirstChild; c != nil; c = c.NextSibling { forEachNode(c, pre, post) } if post != nil { post(n) } }
// Check Content-Type is HTML (e.g., "text/html; charset=utf-8"). ct := resp.Header.Get("Content-Type") if ct != "text/html" && !strings.HasPrefix(ct, "text/html;") { resp.Body.Close() return fmt.Errorf("%s has type %s, not text/html", url, ct) }