我的迭代函数有什么问题

时间:2015-02-27 06:58:01

标签: loops pointers go linked-list

我试图迭代一个简单的链表。这应该是如此简单,但它不起作用。迭代函数包含问题。

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)
    }
}
天哪,我只是没有看到它?我在循环体执行后将头设置为n,它等于下一个节点。不应该是下一个head.Next返回后续节点,直到我们到达一个nil节点并退出循环?

---更新---

我已经提出了以下修改来迭代,它现在更加清晰,实际上是正确的:

func iterate(head *Node) {
    for ; head != nil; head = head.Next {
        fmt.Printf("head %+v head.Next %+v\n", head, head.Next)
    }
}

2 个答案:

答案 0 :(得分:4)

查看For statement spec

  • &#34; init语句&#34;循环的一部分(n := head.Next)仅评估一次。
  • post语句不断将head重置为初始值ngetNext(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
}

答案 1 :(得分:3)

n := head.Next只运行一次。

for ①; ②; ③ { ④ }

中的

它运行① - ②④③ - ②④③ - ②④③ - ...

所以你应该把迭代放在③中,当然,你可以把它放在②或④中但是它不是很明显。