func crawl(document *html.Node, url string) documentInfo {
	// Initialise documentInfo struct.
	info := documentInfo{}
	info.accessibleInternalLinks.links = make([]string, 0)
	info.inaccessibleInternalLinks.links = make([]string, 0)
	info.externalLinks.links = make([]string, 0)

	// Define crawler function.
	var crawler func(*html.Node)

	// Initialize crawler function.
	crawler = func(n *html.Node) {
		// Identify node type.
		switch n.Type {
		// Element node.
		case html.ElementNode:
			// Identify element type.
			switch n.Data {
			// <a> element.
			case anchor:
				l, err := identifyLinkInfo(n.Attr, url)
				if err != nil {
					log.Println("[WARNING] Failed to obtain link information from anchor element:", err)
				} else if l.isExternal {
					info.externalLinks.links = append(info.externalLinks.links, l.href)
					info.externalLinks.count++
				} else if l.isAccessible {
					info.accessibleInternalLinks.links = append(info.accessibleInternalLinks.links, l.href)
					info.accessibleInternalLinks.count++
				} else {
					info.inaccessibleInternalLinks.links = append(info.inaccessibleInternalLinks.links, l.href)
					info.inaccessibleInternalLinks.count++
				}
			// <form> element.
			case form:
				info.containsForm = true
			// <title> element.
			case title:
				if n.FirstChild != nil {
					info.pageTitle = n.FirstChild.Data
				}
			// <h1> to <h6> elements.
			case heading1:
				info.headingCount.h1++
			case heading2:
				info.headingCount.h2++
			case heading3:
				info.headingCount.h3++
			case heading4:
				info.headingCount.h4++
			case heading5:
				info.headingCount.h5++
			case heading6:
				info.headingCount.h6++
			}
		// Doctype node.
		case html.DoctypeNode:
			info.htmlVersion = identifyHTMLVersion(n.Attr)
		}

		// Crawl through children/next sibling of current node.
		for c := n.FirstChild; c != nil; c = c.NextSibling {
			crawler(c)
		}
	}

	// Execute crawler function.
	crawler(document)

	return info
}
// crawl is used to crawl through a provided HTML document and identify
// a given set of properties. These properties are defined and returned
// as a documentInfo struct.
//
// Aside from the document, a url string needs to be provided which defines
// the url in which the document was obtained from. The reason for this
// is so that the crawler can use this to differentiate between internally
// and externally accessible links.
crawl is used to crawl through a provided HTML document and identify
a given set of properties. These properties are defined and returned
as a documentInfo struct.

Aside from the document, a url string needs to be provided which defines
the url in which the document was obtained from. The reason for this
is so that the crawler can use this to differentiate between internally
and externally accessible links.
// crawl is used to crawl through a provided HTML document and identify // a given set of properties . These properties are defined and returned // as a documentInfo struct . // // Aside from the document a url string needs to be provided which defines // the url in which the document was obtained from . The reason for this // is so that the crawler can use this to differentiate between internally // and externally accessible links .
func crawl(document *html.Node, url string) documentInfo {
	info := documentInfo{}
	info.accessibleInternalLinks.links = make([]string, 0)
	info.inaccessibleInternalLinks.links = make([]string, 0)
	info.externalLinks.links = make([]string, 0)
	var crawler func(*html.Node)
	crawler = func(n *html.Node) {
		switch n.Type {
		case html.ElementNode:
			switch n.Data {
			case anchor:
				l, err := identifyLinkInfo(n.Attr, url)
				if err != nil {
					log.Println("[WARNING] Failed to obtain link information from anchor element:", err)
				} else if l.isExternal {
					info.externalLinks.links = append(info.externalLinks.links, l.href)
					info.externalLinks.count++
				} else if l.isAccessible {
					info.accessibleInternalLinks.links = append(info.accessibleInternalLinks.links, l.href)
					info.accessibleInternalLinks.count++
				} else {
					info.inaccessibleInternalLinks.links = append(info.inaccessibleInternalLinks.links, l.href)
					info.inaccessibleInternalLinks.count++
				}
			case form:
				info.containsForm = true
			case title:
				if n.FirstChild != nil {
					info.pageTitle = n.FirstChild.Data
				}
			case heading1:
				info.headingCount.h1++
			case heading2:
				info.headingCount.h2++
			case heading3:
				info.headingCount.h3++
			case heading4:
				info.headingCount.h4++
			case heading5:
				info.headingCount.h5++
			case heading6:
				info.headingCount.h6++
			}
		case html.DoctypeNode:
			info.htmlVersion = identifyHTMLVersion(n.Attr)
		}
		for c := n.FirstChild; c != nil; c = c.NextSibling {
			crawler(c)
		}
	}
	crawler(document)
	return info
}
func crawl ( document * html . Node , url string ) documentInfo { info := documentInfo { } info . accessibleInternalLinks . links = make ( [ ] string , 0 ) info . inaccessibleInternalLinks . links = make ( [ ] string , 0 ) info . externalLinks . links = make ( [ ] string , 0 ) var crawler func ( * html . Node ) crawler = func ( n * html . Node ) { switch n . Type { case html . ElementNode : switch n . Data { case anchor : l , err := identifyLinkInfo ( n . Attr , url ) if err != nil { log . Println ( " " , err ) } else if l . isExternal { info . externalLinks . links = append ( info . externalLinks . links , l . href ) info . externalLinks . count ++ } else if l . isAccessible { info . accessibleInternalLinks . links = append ( info . accessibleInternalLinks . links , l . href ) info . accessibleInternalLinks . count ++ } else { info . inaccessibleInternalLinks . links = append ( info . inaccessibleInternalLinks . links , l . href ) info . inaccessibleInternalLinks . count ++ } case form : info . containsForm = true case title : if n . FirstChild != nil { info . pageTitle = n . FirstChild . Data } case heading1 : info . headingCount . h1 ++ case heading2 : info . headingCount . h2 ++ case heading3 : info . headingCount . h3 ++ case heading4 : info . headingCount . h4 ++ case heading5 : info . headingCount . h5 ++ case heading6 : info . headingCount . h6 ++ } case html . DoctypeNode : info . htmlVersion = identifyHTMLVersion ( n . Attr ) } for c := n . FirstChild ; c != nil ; c = c . NextSibling { crawler ( c ) } } crawler ( document ) return info }
crawl is used to crawl through a provided HTML document and identify
a given set of properties.
crawl is used to crawl through a provided HTML document and identify a given set of properties .
// Initialise documentInfo struct. // Define crawler function. // Initialize crawler function. // Identify node type. // Element node. // Identify element type. // <a> element. // <form> element. // <title> element. // <h1> to <h6> elements. // Doctype node. // Crawl through children/next sibling of current node. // Execute crawler function.