使用Goldmark在Golang中添加ChildNode会导致堆栈溢出。

huangapple go评论87阅读模式
英文:

Appending a ChildNode using Goldmark In golang is causing a stack over flow

问题

我一直在使用Go中的Goldmark进行尝试,我对Go还不太熟悉,所以不确定我是否做得正确。我一直在阅读文档,但是我感到有点困惑,不明白为什么会出现这种情况。

我解析了一个Markdown文件,并使用ast.Walk遍历了ast。

我的目标是在列表项下方插入一个子列表。

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
})

然而,每当我运行这段代码时,我都会得到以下错误:

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

我认为这是因为在下一次迭代中添加了一个新节点并访问该节点所导致的。然而,我不确定如何跳过新节点。

英文:

I've been playing around with Goldmark in Go, I'm new to go so I'm not sure if i'm doing this correctly. I've been reading the documentation but, I feel a little confused as to why this is happening.

I've parsed a markdown file and used the ast.Walk to walk the ast.

My goal is to inject a sub list under a 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 ever 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 being caused by adding a new node and visiting that node on the next iteration. However I'm not fully sure how to skip over the new node.

答案1

得分: 1

你是正确的,堆栈溢出错误是由于访问新节点引起的。

为了解决这个问题,你可以记录添加的节点,并在 walk 函数中跳过它们。

// 用于记录添加的节点
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 {
				// 跳过已添加的节点
				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)

			// 记录已添加的节点
			added[subList] = true
		}
	}

	return ast.WalkContinue, nil
})
英文:

You are correct that the stack overflow error is caused by the visiting of the new nodes.

To address the issue, you can record the added nodes and skip them in the walk func.

// 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
})

huangapple
  • 本文由 发表于 2023年6月27日 10:30:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/76561263.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定