Go语言为什么采用晚绑定?
创建一个空数组,数组元素类型为 void -> int 的函数,最后遍历数组并依次调用数组内的函数
~/go % cat arr_of_fns.go 0:31 package main
import "fmt"
const LS_SIZE int = 5
func main() {
// Creating empty array
var fns [LS_SIZE]func() int
// Loop
for i := 0; i < LS_SIZE; i++ {
fns[i] = func() int {
return i
}
}
for n := 0; n < LS_SIZE; n++ {
fmt.Printf("fns[%d]: %d\n", n, fns[n]()) } }
~/go % go run arr_of_fns.go 0:31
fns[0]: 5
fns[1]: 5
fns[2]: 5
fns[3]: 5
fns[4]: 5
- 循环变量
i
在离开循环块后就无法访问了,这一点和许多编译型语言一致 - 但每个匿名函数返回的值一样,是循环变量最终的值,这一点又和 Python,Ruby,Groovy 等语言一样
为什么 Go 采用晚绑定?Ruby,Python 可以通过给函数添加默认参数,将每次循环的值保存下来。Go 要如何解决呢?
回复
1个回答
test
2024-07-08
除了一楼的方式外,你还可以:
package main
import "fmt"
const LS_SIZE int = 5
func main() {
// Creating empty array
var fns [LS_SIZE]func(x int) int // 更改此处数组函数声明
// Loop
for i := 0; i < LS_SIZE; i++ {
fns[i] = func(i int) int { // 有入参
return i
}
}
for n := 0; n < LS_SIZE; n++ {
fmt.Printf("fns[%d]: %d\n", n, fns[n](n)) // 带入入参
}
}
输出:
fns[0]: 0
fns[1]: 1
fns[2]: 2
fns[3]: 3
fns[4]: 4
这种闭包问题很常见,fns的值在若干次循环中都是同一个内存地址,而i也在若干次循环后,更新到了 i++
后的值。所以在你调用 fmt.Printf("fns[%d]: %d\n", n, fns[n]())
的时候,不论是 fns[0]()
还是 fns[4]()
等等,代表的都是同一个函数对象,fns[n]()
中i得值已经在上一个for循环执行完毕被更新到了5,而故而你最终得到的结果都是5.
回复
适合作为回答的
- 经过验证的有效解决办法
- 自己的经验指引,对解决问题有帮助
- 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
- 询问内容细节或回复楼层
- 与题目无关的内容
- “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容