将字符串递归地附加到切片会导致golang中出现内存不足错误
我试图解析一个HTML页面并打印它的链接。 我将遍历已解析的Html树,递归地向字符串片段添加链接。 当我出现内存不足错误时,我遗漏了一些内容 这是我的密码:将字符串递归地附加到切片会导致golang中出现内存不足错误,go,out-of-memory,slice,Go,Out Of Memory,Slice,我试图解析一个HTML页面并打印它的链接。 我将遍历已解析的Html树,递归地向字符串片段添加链接。 当我出现内存不足错误时,我遗漏了一些内容 这是我的密码: package parser import ( "errors" "io" "golang.org/x/net/html" ) //URLParser returns all the urls inside a html page type URLParser struct { } //GetURLS re
package parser
import (
"errors"
"io"
"golang.org/x/net/html"
)
//URLParser returns all the urls inside a html page
type URLParser struct {
}
//GetURLS returns all
func (URLParser) GetURLS(htmlInput io.Reader) (*[]string, error) {
result := []string{}
htmlRoot, err := html.Parse(htmlInput)
//result := make([]string, 1000)
if err != nil {
parserError := errors.New("html parser failed with error" + err.Error())
return nil, parserError
}
finalResult := traverseHTMLTree(htmlRoot, &result)
return finalResult, nil
}
func traverseHTMLTree(node *html.Node, result *[]string) *[]string {
if node == nil {
return nil
}
if isLinkElement(node) {
currlink, shouldUse := getURLAttrb(node.Attr)
if shouldUse {
*result = append(*result, currlink)
}
}
for currNode := node.FirstChild; currNode != nil; currNode = currNode.NextSibling {
currRest := traverseHTMLTree(currNode, result)
if currRest != nil {
*result = append(*currRest, *result...)
}
}
return result
}
func getURLAttrb(attr []html.Attribute) (string, bool) {
for i := 0; i < len(attr); i++ {
if attr[i].Key == "href" {
return attr[i].Val, true
}
}
return "", false
}
func isLinkElement(node *html.Node) bool {
if node.Type == html.ElementNode {
if node.Data == "a" {
return true
}
}
return false
}
包解析器
进口(
“错误”
“io”
“golang.org/x/net/html”
)
//URLParser返回html页面内的所有URL
类型URLParser struct{
}
//getURL返回所有
func(URLParser)getURL(htmlInput io.Reader)(*[]字符串,错误){
结果:=[]字符串{}
htmlRoot,err:=html.Parse(htmlInput)
//结果:=make([]字符串,1000)
如果错误!=零{
parserError:=errors.New(“html解析器失败,出现错误”+err.error())
返回nil,parserror
}
finalResult:=遍历HtmlTree(htmlRoot和结果)
返回最终结果,零
}
func traverseHTMLTree(节点*html.node,结果*[]字符串)*[]字符串{
如果节点==nil{
归零
}
如果IsLink元素(节点){
currlink,shouldUse:=getURLAttrb(node.Attr)
如果应该使用{
*结果=追加(*结果,currlink)
}
}
对于currNode:=node.FirstChild;currNode!=nil;currNode=currNode.NextSibling{
currRest:=traverseHTMLTree(currNode,结果)
如果currRest!=零{
*结果=追加(*currest,*结果…)
}
}
返回结果
}
func geturlatrb(attr[]html.Attribute)(字符串,bool){
对于i:=0;i
当只是试图打印到stdout的链接时,它工作得非常好,因此它必须与我处理切片的方式一致。对于HTML树中的每个节点,您都在递归地将结果数组的内容添加到自身中。这应该增长得很快 请注意,当您检查if
isLinkElement
时,您将该项添加到结果列表中
然后,对于html树的每个元素,将结果数组的内容附加到自身,使其加倍
您正在将指针传递给一个切片。您有效地为整个程序使用了一个片段,并不断添加到其中。从traverseHTMLTree返回的是同一个片段,而不是它的副本。所以它一直在增长
一种解决方法是:不要将指针传递到切片。传递当前切片,更新它,然后返回新切片。传递切片(而不是指向它的指针)将导致每次复制当前切片,否?否。传递数组将导致。传递一个切片将不会。更清楚地说,传递一个切片将复制切片,即(指针、len、cap)。它不会复制底层数组。基本上是从代码中的任何位置删除“*”吗?我不是这么说的。每个元素的数组仍在翻倍。删除此项:
*result=append(*currRest,*result…)