我的迭代函数有什么问题
What is wrong with my iterate function
我正在尝试遍历一个简单的链表。这应该很简单,但它不起作用。迭代函数包含问题。
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}
为了好玩,我尝试了另一个版本的迭代循环,它使用一个函数来获取 .Next。我的想法是,由于某种循环优化,可能 head.Next 总是指向我原来的头。这个理论似乎不正确。
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 return 不应该是后续节点,直到我们到达一个 nil 节点并退出循环吗?
---更新---
我想出了以下修改来迭代,它现在更清晰而且实际上是正确的:
func iterate(head *Node) {
for ; head != nil; head = head.Next {
fmt.Printf("head %+v head.Next %+v\n", head, head.Next)
}
}
- 循环的 "init statement" 部分 (
n := head.Next
) 仅计算一次。
- post语句不断将
head
重置为n
的初始值(getNext(head)
)。
因此无限循环。
将 n := getNext(head)
放在 循环中应该会更好,如 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
}
n := head.Next
只 运行 一次。
在for ①; ②; ③ { ④ }
it 运行s ① - ②④③ - ②④③ - ②④③ - ...
所以应该把迭代放在③里,当然也可以放在②或④里,但不是很明显。
我正在尝试遍历一个简单的链表。这应该很简单,但它不起作用。迭代函数包含问题。
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}
为了好玩,我尝试了另一个版本的迭代循环,它使用一个函数来获取 .Next。我的想法是,由于某种循环优化,可能 head.Next 总是指向我原来的头。这个理论似乎不正确。
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 return 不应该是后续节点,直到我们到达一个 nil 节点并退出循环吗?
---更新---
我想出了以下修改来迭代,它现在更清晰而且实际上是正确的:
func iterate(head *Node) {
for ; head != nil; head = head.Next {
fmt.Printf("head %+v head.Next %+v\n", head, head.Next)
}
}
- 循环的 "init statement" 部分 (
n := head.Next
) 仅计算一次。 - post语句不断将
head
重置为n
的初始值(getNext(head)
)。
因此无限循环。
将 n := getNext(head)
放在 循环中应该会更好,如 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
}
n := head.Next
只 运行 一次。
在for ①; ②; ③ { ④ }
it 运行s ① - ②④③ - ②④③ - ②④③ - ...
所以应该把迭代放在③里,当然也可以放在②或④里,但不是很明显。