关于Golang中lambda函数/闭包的一些混淆

时间:2016-12-06 08:18:58

标签: go lambda closures

package main
import (
    "fmt"
)
func main(){
    f,val,val1:=fibonacci()
    fmt.Println(val,val1)
    for i:=0;i<=10;i++ {
        fmt.Println(f(i),val,val1)
    }
    _,val,val1=fibonacci()
    fmt.Println(val,val1)
}
func fibonacci()(func(n int)int,int,int){
    var val int
    var val1 int
    f:=func(n int)int{
        if n==0||n==1{
            val,val1=1,1
        }else{
            val,val1=val+val1,val
        }
        return val
    }
    fmt.Println("fibonacci val =",val,"val1 =",val1)
    return f,val,val1
}
  

这是我的解释斐波纳契的代码而不使用递归   阅读有关lambda函数/闭包的内容。 Go纪录片说a   关闭将捕获一些外部状态。我的理解是   闭包将保留函数状态的副本   声明。这些状态只是副本,无论我做什么都不会   修改原文,就是这样吗?

2 个答案:

答案 0 :(得分:0)

来自您的测试代码:https://play.golang.org/p/pajT2bAIe2

你的斐波纳契函数正在计算序列中的第n个数字,前提是你正在以递增的方式调用它。但是从初始调用fibonacci返回的值不是指向那些整数值的指针(或引用),它们只是那时整数的值,将它们视为复制出函数,尝试使用整数指针代替:https://play.golang.org/p/-vLja7Fpsq

package main

import (
    "fmt"
)

func main() {
    f, val, val1 := fibonacci()
    fmt.Println(val, val1)
    for i := 0; i <= 10; i++ {
        fmt.Println(f(i), *val, *val1) //dereference the pointer to get its value at the current time
    }
    _, val, val1 = fibonacci()
    fmt.Println(*val, *val1)
}
func fibonacci() (func(n int) int, *int, *int) {
    var val int
    var val1 int
    f := func(n int) int {
        if n == 0 || n == 1 {
            val, val1 = 1, 1
        } else {
            val, val1 = val+val1, val
        }
        return val
    }
    fmt.Println("fibonacci val =", val, "val1 =", val1)
    return f, &val, &val1 // return pointers to the closured values instead of just the values
}

答案 1 :(得分:0)

虽然你已经接受了上述答案,但我还是给出了另一种解释。您收到循环操作的最后一个值的原因与Go的词法范围有关。 for loop引入了一个新的词法块,其中的值由它的内存地址引用,因此通过指针而不是它的值来引用。为了获得该值,您必须取消引用。

每次for循环进行迭代时,处理的值都指向相同的内存地址。此循环创建的所有函数值&#34; capture&#34;并分享相同的变量 - 以及可寻址的存储位置,而不是它在该特定时刻的价值。因此,当最后一次迭代完成时,变量保存最后一步的值。

这种操作的更好方法是使用goroutine,因为在这些情况下,您不是通过共享相同的内存地址进行通信,而是通过通信共享内存。

这是使用goroutine的更优雅的解决方案:

package main

import (
    "fmt"
)

func fibonacci(ch chan interface{}, quit chan struct{}) {
    x, y := 1, 1
    for {
        select {
        case ch <- x:
            x, y = y, x+y
            fmt.Println(x , y)
        case <-quit:
            fmt.Println("Quiting...")
            return
        }
    }
}

func main() {
    ch := make(chan interface{})
    quit := make(chan struct{})

    go func() {
        for i := 0; i < 10; i++ {
            <-ch
        }
        quit <- struct{}{}
    }()

    fibonacci(ch, quit)
}

https://play.golang.org/p/oPQgXWyV9u