Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将字符串递归地附加到切片会导致golang中出现内存不足错误_Go_Out Of Memory_Slice - Fatal编程技术网

将字符串递归地附加到切片会导致golang中出现内存不足错误

将字符串递归地附加到切片会导致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

我试图解析一个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 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…)