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 关闭将捕获一些外部状态。我的理解是 闭包将保留函数状态的副本 声明。这些状态只是副本,无论我做什么都不会 修改原文,就是这样吗?
答案 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)
}