英文:
What is wrong with my iterate function
问题
我正在尝试迭代一个简单的链表。这应该很简单,但是它不起作用。问题出在iterate函数中。
package main
import (
"fmt"
"time"
)
type Node struct {
Next *Node
Value int
}
func main() {
//Load up 100 *Node in a linked list (albeit a simple one)
head := &Node{Value: 0}
current := head
for i := 1; i < 100; i++ {
current.Next = &Node{Value: i}
current = current.Next
fmt.Printf("current %p %+v\n", current, current)
}
iterate(head)
}
//Iterate through the list starting at head. It never
//advances past the first "Next", loops forever.
func iterate(head *Node) {
for n := head.Next; n != nil; head = n {
fmt.Printf("head %+v n %+v\n", head, n)
time.Sleep(time.Second * 1)
}
}
iterate函数的输出结果如下:
head &{Next:0x20818c230 Value:0} n &{Next:0x20818c280 Value:1}
head &{Next:0x20818c280 Value:1} n &{Next:0x20818c280 Value:1}
head &{Next:0x20818c280 Value:1} n &{Next:0x20818c280 Value:1}
head &{Next:0x20818c280 Value:1} n &{Next:0x20818c280 Value:1}
head &{Next:0x20818c280 Value:1} n &{Next:0x20818c280 Value:1}
出于好奇,我尝试了另一个版本的iterate循环,它使用一个函数来获取.Next。我的想法是,也许head.Next总是指向原始head,因为存在某种循环优化。但这个理论似乎是错误的。
func iterate(head *Node) {
getNext := func (n *Node) *Node {
return n.Next
}
for n := getNext(head); n != nil; head = n {
fmt.Printf("head %+v n %+v\n", head, n)
time.Sleep(time.Second * 1)
}
}
天哪,我是不是看不到问题所在?我在循环体执行后将head设置为n,即下一个节点。难道下一个head.Next不应该返回后续的节点,直到我们到达一个空节点并退出循环吗?
--- 更新 ---
我对iterate进行了以下修改,现在更加简洁且正确:
func iterate(head *Node) {
for ; head != nil; head = head.Next {
fmt.Printf("head %+v head.Next %+v\n", head, head.Next)
}
}
英文:
I am attempting to iterate over a simple linked list. This should be so simple, but it's not working. The iterate function contains the issue.
package main
import (
"fmt"
"time"
)
type Node struct {
Next *Node
Value int
}
func main() {
//Load up 100 *Node in a linked list (albeit a simple one)
head := &Node{Value: 0}
current := head
for i := 1; i < 100; i++ {
current.Next = &Node{Value: i}
current = current.Next
fmt.Printf("current %p %+v\n", current, current)
}
iterate(head)
}
//Iterate through the list starting at head. It never
//advances past the first "Next", loops forever.
func iterate(head *Node) {
for n := head.Next; n != nil; head = n {
fmt.Printf("head %+v n %+v\n", head, n)
time.Sleep(time.Second * 1)
}
}
The output of iterate looks something like:
head &{Next:0x20818c230 Value:0} n &{Next:0x20818c280 Value:1}
head &{Next:0x20818c280 Value:1} n &{Next:0x20818c280 Value:1}
head &{Next:0x20818c280 Value:1} n &{Next:0x20818c280 Value:1}
head &{Next:0x20818c280 Value:1} n &{Next:0x20818c280 Value:1}
head &{Next:0x20818c280 Value:1} n &{Next:0x20818c280 Value:1}
For kicks I tried another version of the iterate loop that uses a function to fetch .Next. My thinking was that maybe head.Next was always pointing at my original head due to some sort of loop optimization. That theory seems incorrect.
func iterate(head *Node) {
getNext := func (n *Node) *Node {
return n.Next
}
for n := getNext(head); n != nil; head = n {
fmt.Printf("head %+v n %+v\n", head, n)
time.Sleep(time.Second * 1)
}
}
Gosh, am I just not seeing it? I set head to n after the loop body executes which is equal to the next Node. Shouldn't the next head.Next return the subsequent Node until we get to a nil node and exit the loop?
--- Update ---
I've come up with the following modification to iterate which is so much cleaner and actually correct now:
func iterate(head *Node) {
for ; head != nil; head = head.Next {
fmt.Printf("head %+v head.Next %+v\n", head, head.Next)
}
}
答案1
得分: 4
查看For
语句规范:
- 循环的“初始化语句”部分(
n := head.Next
)只会被评估一次。 - 后置语句会将
head
重置为n
的初始值(getNext(head)
)。
因此导致了无限循环。
将n := getNext(head)
放在循环内部会更好,就像这个可工作的示例一样:
for n := head; n != nil; head = n {
fmt.Printf("head %+v n %+v\n", head, n)
time.Sleep(time.Second * 1)
n = head.Next
}
英文:
Looking at the For
statement spec:
- The "init statement" part of your loop (
n := head.Next
) is evaluated only once. - The post statement keeps resetting
head
to the initial value ofn
(getNext(head)
).
Hence the inifinite loop.
Putting n := getNext(head)
within the loop should be better, as in this working example:
for n := head; n != nil; head = n {
fmt.Printf("head %+v n %+v\n", head, n)
time.Sleep(time.Second * 1)
n = head.Next
}
答案2
得分: 3
n := head.Next
只运行一次。
在 for ①; ②; ③ { ④ }
中,
它运行 ① - ②④③ - ②④③ - ②④③ - ...
所以你应该将迭代放在 ③ 中,当然,你也可以将其放在 ② 或 ④ 中,但这不太明显。
英文:
n := head.Next
just run once.
in for ①; ②; ③ { ④ }
it runs ① - ②④③ - ②④③ - ②④③ - ...
so you should put the iteration in ③, of course, you can put it in ② or ④ but it's not very obvious.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论