package main import ( "Study/src/study/day7Function/HtmlTools" "fmt" "golang.org/x/net/html" "reflect" ) func main() { // 同样的,函数可以作为参数传入另一个函数 // forEachNode针对每个结点x,都会调用pre(x)和post(x)。 // pre和post都是可选的。 // 遍历孩子结点之前,pre被调用 // 遍历孩子结点之后,post被调用 var forEachNode func(n *html.Node, pre, post func(n *html.Node)) forEachNode = func(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) } } var depth int var ExcludeNodes []string = []string{ "link", "img", "meta", } // 断言 m, _ := ToMapSetStrictE(ExcludeNodes) ExcludeNodesMap := m.(map[string]struct{}) startElemen := func(n *html.Node) { if n.Type == html.ElementNode { fmt.Printf("%*s<%s", depth*2, "", n.Data) for _, attr := range n.Attr { fmt.Printf(" %s=\"%s\"", attr.Key, attr.Val) } // 检测单节点 if _, ok := ExcludeNodesMap[n.Data]; ok { fmt.Println(" />") } else { fmt.Println(">") } depth++ } } endElement := func(n *html.Node) { if n.Type == html.ElementNode { depth-- // 检测单节点 if _, ok := ExcludeNodesMap[n.Data]; !ok { fmt.Printf("%*s\n", depth*2, "", n.Data) } } } forEachNode(HtmlTools.GetHtml(), startElemen, endElement) } // 借助一个空接口,使切片转为map func ToMapSetStrictE(i interface{}) (interface{}, error) { // check param if i == nil { return nil, fmt.Errorf("unable to converts %#v of type %T to map[interface{}]struct{}", i, i) } t := reflect.TypeOf(i) kind := t.Kind() if kind != reflect.Slice && kind != reflect.Array { return nil, fmt.Errorf("the input %#v of type %T isn't a slice or array", i, i) } // execute the convert v := reflect.ValueOf(i) mT := reflect.MapOf(t.Elem(), reflect.TypeOf(struct{}{})) mV := reflect.MakeMapWithSize(mT, v.Len()) for j := 0; j < v.Len(); j++ { mV.SetMapIndex(v.Index(j), reflect.ValueOf(struct{}{})) } return mV.Interface(), nil }