在递归函数运行期间,切片中指针的内容发生了变化。

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

golang - Content of a pointer in a slice changes during recursive function run

问题

func getAllCertainDivs(className string, idName string, htmlTag *HtmlTag, matchingDivs *[]*HtmlTag) {
fmt.Println(htmlTag.Class)
if htmlTag.XMLName.Local == "div" {
if htmlTag.Class == className && htmlTag.Id == idName {
*matchingDivs = append(*matchingDivs, htmlTag)
}
}

for _, tag := range htmlTag.ChildTags {
    getAllCertainDivs(className, idName, &tag, matchingDivs)
}

}

在上面的函数中,你可以看到,我将一个切片的指针传递给了getAllCertainDivs函数。在某个点上,一个HtmlTag指针被添加到了matchingDivs切片中。在append之后,我检查了matchingDivs切片的内容,然后再次递归调用函数自身。然后,在if语句的下面,我调用函数自身进行递归一次。我停在了fmt.Println(htmlTag.Class)这一行,并再次检查了matchingDivs切片的内容。然而,内容与之前完全不同。

只进行了一次append操作,为什么内容会改变?在每次将HtmlTag指针传递给下一个递归调用时,golang是否使用相同的指针?

英文:
func getAllCertainDivs(className string, idName string, htmlTag *HtmlTag, matchingDivs *[]*HtmlTag) {
	fmt.Println(htmlTag.Class)
	if htmlTag.XMLName.Local == "div" {
		if htmlTag.Class == className && htmlTag.Id == idName {
			*matchingDivs = append(*matchingDivs, htmlTag)
		}
	}

	for _, tag := range htmlTag.ChildTags {
		getAllCertainDivs(className, idName, &tag, matchingDivs)
	}
}

In the function above, as you can see, I pass a pointer of a slice into the getAllCertainDivs function. At a point a HtmlTag pointer is pushed into the slice matchingDivs. After the append I check the content of the matchingDiv slice, before letting the function call itself recursively again. Then below the if where append was made, the function calls itself recursively one time. And I stop at the fmt.Println(htmlTag.Class) and check the content of matchingDivs slice again. And the content is completely different than before.

There has only been one append, how can the content change ? Does golang use the same HtmlTag pointer, everytime I pass it into next recursive call ?

答案1

得分: 1

tag变量在循环开始时声明一次,并且在每次迭代中被覆盖。这与FAQ中的问题相同:"What happens with closures running as goroutines?"

您可以在每次迭代期间声明一个新变量,以获得一个唯一的指针用于函数调用:

for _, tag := range htmlTag.ChildTags {
    tag := tag
    getAllCertainDivs(className, idName, &tag, matchingDivs)
}

或者您可以省略范围值,并直接使用索引:

for i := range htmlTag.ChildTags {
    getAllCertainDivs(className, idName, &htmlTag.ChildTags[i], matchingDivs)
}
英文:

The tag variable is declared once at the start of the loop, and the value of tag is overwritten on each iteration. This is the same problem you see in the FAQ with: "What happens with closures running as goroutines?"

You can declare a new variable during each iteration to get a unique pointer for the function call:

for _, tag := range htmlTag.ChildTags {
    tag := tag
    getAllCertainDivs(className, idName, &tag, matchingDivs)
}

Alternatively you can elide the range value, and use the index directly:

for i := range htmlTag.ChildTags {
    getAllCertainDivs(className, idName, &htmlTag.ChildTags[i], matchingDivs)
}

huangapple
  • 本文由 发表于 2016年2月17日 02:44:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/35440619.html
匿名

发表评论

匿名网友

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

确定