1. 程式人生 > >PHP和Go中的閉包變量作用域

PHP和Go中的閉包變量作用域

reac 繼續 循環 我們 get .com https Golan 例子

關於閉包函數,之前在聊過。這裏忽略了一點,不管是Go/Php/Python,閉包都存在局部變量的引用。
我們還是先看個例子:

PHP示例:

$list = [];
for ($i = 0; $i < 3; $i++) {
    $list[] = function(){
        global $i;
        return $i;
    };
}
foreach ($list as $fun) {
    echo $fun().PHP_EOL;
}

以上輸出:

3
3
3

相信很多朋友會說:不是應該輸出 0 1 2嗎?
好,繼續,我們來看一個Golang的閉包示例:

package main
import 
"fmt" func main() { var list []func() int for i := 0; i < 3; i++ { list = append(list, func() int { return i }) } for _, fun := range list { fmt.Printf("%p = %v\n", fun, fun()) } }

以上輸出:(這裏輸出的內存地址會根據機器的不同而有所不同,甚至相同的程序在不同的機器上執行後也會有不同的內存地址)

0x48fd70 = 3
0x48fd70 = 3 0x48fd70 = 3

有興趣的博友可以寫個同樣的Python示例,相信結果同出一轍。那麽為什麽結果是 3?
重點:閉包函數在調用完畢後,i變量就是從循環條件中的 i++開始,也就是 原本是 0,1,2循環結束,那麽閉包調用結束後此時 i從i++開始也就是3.
其實這個不難理解:
PHP:

$list = [];
for ($i = 0; $i < 3; $i++) {
    echo $i.PHP_EOL; // 輸出 0 1 2
}
echo $i.PHP_EOL;// 輸出 3

GO:

package main
import "fmt"
func main() {
    
var i int for i = 0; i < 3; i++ { fmt.Printf("i = %v\n", i) } fmt.Printf("i = %v\n", i) }
i = 0
i = 1
i = 2
i = 3

結論:循環結束後變量i 從i++開始。

PHP和Go中的閉包變量作用域