GolangStudy/src/study/day7Function/Practice/Practice5.7.go

84 lines
2.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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</%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
}