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

appending strings to a slice recursively causes out of memory error in golang

我正在尝试解析 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
}

当我只是尝试将链接打印到 stdout 时,它工作得很好,所以它必须与我处理切片的方式有关..

对于 HTML 树中的每个节点,您递归地将结果数组的内容添加到自身。那应该会增长得很快。

请注意,当您检查是否 isLinkElement 时,您将项目添加到结果列表中。

然后对于 html 树的每个元素,将结果数组的内容附加到自身,使其加倍。

您正在传递一个指向切片的指针。您有效地为整个程序使用了一个切片,并不断添加到它。您从遍历 HTML 树中 return 得到的是同一个切片,而不是它的副本。所以它一直在增长。

一种解决方法是:不要将指针传递给切片。传递当前切片,更新它,return 新切片。