Home >Backend Development >Golang >Using Goldmark to attach ChildNode in golang causes stack overflow

Using Goldmark to attach ChildNode in golang causes stack overflow

PHPz
PHPzforward
2024-02-08 20:42:11971browse

在 golang 中使用 Goldmark 附加 ChildNode 会导致堆栈溢出

Question content

I've been using goldmark in go and I'm new to it so I'm not sure if I'm doing this correctly. I've been reading the documentation, but I'm a little confused as to why this is happening.

I have parsed a markdown file and used ast.walk to walk through the ast.

My goal is to inject a sublist under the list item.

ast.walk(doc, func(n ast.node, entering bool) (ast.walkstatus, error) {
    if entering {
        if n.kind() == ast.kindlistitem {
            sublist := ast.newlist(0)
            sublistitem := ast.newlistitem(0)
            sublist.appendchild(sublist, sublistitem)

            leaf := ast.newstring([]byte("hello"))
            sublistitem.appendchild(sublistitem, leaf)
            n.appendchild(n, sublist)
        }
    }

    return ast.walkcontinue, nil
})

However, when I run this, I get

runtime: goroutine stack exceeds 1000000000-byte limit
runtime: sp=0xc04f9803c8 stack=[0xc04f980000, 0xc06f980000]
fatal error: stack overflow

I think this is caused by adding a new node and accessing that node on the next iteration. But I'm not entirely sure how to skip new nodes.


Correct answer


You are right, the stack overflow error is caused by the access of a new node.

To solve this problem, you can record the added nodes and skip them in the walk function.

// for recording the added nodes
added := make(map[*ast.List]bool)

ast.Walk(doc, func(n ast.Node, entering bool) (ast.WalkStatus, error) {
    if entering {
        if n.Kind() == ast.KindList {
            if _, ok := added[n.(*ast.List)]; ok {
                // skip the added node
                return ast.WalkSkipChildren, nil
            }
        }
        if n.Kind() == ast.KindListItem {
            subList := ast.NewList(0)
            subListItem := ast.NewListItem(0)
            subList.AppendChild(subList, subListItem)

            leaf := ast.NewString([]byte("Hello"))
            subListItem.AppendChild(subListItem, leaf)
            n.AppendChild(n, subList)

            // record the added node
            added[subList] = true
        }
    }

    return ast.WalkContinue, nil
})

The above is the detailed content of Using Goldmark to attach ChildNode in golang causes stack overflow. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete