Go语言为什么采用晚绑定?

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 要如何解决呢?


回答:

除了一楼的方式外,你还可以:

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.


回答:

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

回到顶部