Go语言为什么采用晚绑定?
创建一个空数组,数组元素类型为 void -> int 的函数,最后遍历数组并依次调用数组内的函数
~/go % cat arr_of_fns.go 0:31 package mainimport "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 要如何解决呢?
回答:
除了一楼的方式外,你还可以:
package mainimport "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]: 0fns[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.
回答:
func main() { var fns [LS_SIZE]func() int
for i := 0; i < LS_SIZE; i++ {
// 加个局部变量不就可以了
idx := i
fns[i] = func() int {
return idx
}
}
for n := 0; n < LS_SIZE; n++ {
fmt.Printf("fns[%d]: %d\n", n, fns[n]())
}
}
以上是 Go语言为什么采用晚绑定? 的全部内容, 来源链接: utcz.com/p/938788.html