dongtidai6519 2013-10-08 22:58
浏览 75
已采纳

直接调用函数和使用指针之间的行为不同

I am new to Go language and got confused with the following code

package main

import "fmt"

// fibonacci is a function that returns
// a function that returns an int.
func fibonacci() func() int {
    previous := 0
    current := 1
    return func () int{
        current = current+previous
        previous = current-previous
        return current

    }
}

func main() {
    f := fibonacci
    for i := 0; i < 10; i++ {
        fmt.Println(f()())
    }
}

This code is supposed to print out the Fibonacci Sequence (first 10), but only print out 10 times 1. but if I change the code to:

func main() {
    f := fibonacci()
    for i := 0; i < 10; i++ {
        fmt.Println(f())
    }
}

Then it is working fine. The output is the Fibonacci sequence.

Could any one help me explain this?

Thanks

  • 写回答

3条回答 默认 最新

  • douguwo2275 2013-10-08 23:47
    关注

    This has to do with how variables are encapsulated in closures after returning the closure. Consider the following example (live code on play):

    func newClosure() func() {
        i := 0
        fmt.Println("newClosure with &i=", &i)
        return func() {
            fmt.Println(i, &i)
            i++
        }
    }    
    
    func main() {
        a := newClosure()
        a()
        a()
        a()
        b := newClosure()
        b()
        a()
    }
    

    Running this code will yield something like the following output. I annotated which line comes from which statement:

    newClosure with &i= 0xc010000000    // a := newClosure()
    0 0xc010000000                      // a()
    1 0xc010000000                      // a()
    2 0xc010000000                      // a()
    newClosure with &i= 0xc010000008    // b := newClosure()
    0 0xc010000008                      // b()
    3 0xc010000000                      // a()
    

    In the example, the closure returned by newClosure encapsulates the local variable i. This corresponds to current and the like in your code. You can see that a and b have different instances of i, or else the call b() would've printed 3 instead. You can also see that the i variables have different addresses. (The variable is already on the heap as go does not have a separate stack memory, so using it in the closure is no problem at all.)

    So, by generating a new closure you're automatically creating a new context for the closure and the local variables are not shared between the closures. This is the reason why creating a new closure in the loop does not get you further.

    The equivalent in for your code in terms of this example would be:

    for i:=0; i < 10; i++ {
        newClosure()()
    }
    

    And you've already seen by the output that this will not work.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥15 用visual studi code完成html页面
  • ¥15 聚类分析或者python进行数据分析
  • ¥15 逻辑谓词和消解原理的运用
  • ¥15 三菱伺服电机按启动按钮有使能但不动作
  • ¥15 js,页面2返回页面1时定位进入的设备
  • ¥50 导入文件到网吧的电脑并且在重启之后不会被恢复
  • ¥15 (希望可以解决问题)ma和mb文件无法正常打开,打开后是空白,但是有正常内存占用,但可以在打开Maya应用程序后打开场景ma和mb格式。
  • ¥20 ML307A在使用AT命令连接EMQX平台的MQTT时被拒绝
  • ¥20 腾讯企业邮箱邮件可以恢复么
  • ¥15 有人知道怎么将自己的迁移策略布到edgecloudsim上使用吗?