dongzhan2029 2015-02-27 06:58
浏览 51
已采纳

我的迭代函数有什么问题

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
", 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
", 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
", 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
", head, head.Next)
    }
}
  • 写回答

2条回答 默认 最新

  • douxin2003 2015-02-27 07:07
    关注

    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 of n (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
    ", head, n)
        time.Sleep(time.Second * 1)
        n = head.Next
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 树莓派与pix飞控通信
  • ¥15 自动转发微信群信息到另外一个微信群
  • ¥15 outlook无法配置成功
  • ¥30 这是哪个作者做的宝宝起名网站
  • ¥60 版本过低apk如何修改可以兼容新的安卓系统
  • ¥25 由IPR导致的DRIVER_POWER_STATE_FAILURE蓝屏
  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题