/
e5.1.go
67 lines (59 loc) · 1.73 KB
/
e5.1.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
/* Change the 'findlinks1' program to traverse the 'n.FirstChild' linked list
using recursive calls to 'visit' instead of a 'for' loop */
// Findlinks1 prints the links in an HTML document read from the standard input
// run as (in $GOPATH/bin) './fetch <url> | ./findlinks1.5'
package main
import (
"fmt"
"os"
"golang.org/x/net/html"
)
func main() {
doc, err := html.Parse(os.Stdin)
if err != nil {
fmt.Fprintf(os.Stderr, "findlinks1: &v\n, err")
os.Exit(1)
}
for _, link := range visit(nil, doc) {
fmt.Println(link)
}
}
// visit appends to 'links' each link found in 'n' and returns the result.
// Uses recursion to traverse the tree
func visit(links []string, n *html.Node) []string {
if n.Type == html.ElementNode && n.Data == "a" {
for _, a := range n.Attr {
if a.Key == "href" {
links = append(links, a.Val)
}
}
}
links, n = nextNode(links, n.FirstChild)
return links
}
// nextNode uses recursion to traverse the FirstChild/NextSibling linked list
func nextNode(links []string, current *html.Node) ([]string, *html.Node) {
if current != nil {
links = visit(links, current)
next := current.NextSibling
return nextNode(links, next)
}
return links, current
}
/* Original visit function as found in Ch5.2 of "The Go Programming Language" (Donovan, Kernighan)
Not used - for comparison only */
// visit appends to 'links' each link found in 'n' and returns the result.
// Uses for loop and recursion to traverse the tree
func visitOG(links []string, n *html.Node) []string {
if n.Type == html.ElementNode && n.Data == "a" {
for _, a := range n.Attr {
if a.Key == "href" {
links = append(links, a.Val)
}
}
}
for c := n.FirstChild; c != nil; c = c.NextSibling {
links = visitOG(links, c)
}
return links
}