战魂小筑

讨论群:309800774 知乎关注:http://zhihu.com/people/sunicdavy 开源项目:https://github.com/davyxu

   :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  257 随笔 :: 0 文章 :: 506 评论 :: 0 Trackbacks

看C#例子

            Action[] a = new Action[3];
 
            for (int i = 0; i < 3; i++)
            {
                a[i] = ( ) => { Console.WriteLine(i); };
            }
 
            for (int i = 0; i < 3; i++){
                a[i]();
            }

C#打印结果为3 3 3

 

Golang的例子

    a := make([]func(), 3 )
    
    for i := 0; i < 3; i++ {
        
        a[i]= func( ){
            
            fmt.Println(i)
            
        }    
    
    }
    
    for _, s := range a {
        s()
    }

Golang打印结果为3 3 3

 

最后是Lua的例子

a = {}
 
for i = 1, 3 do
 
    table.insert( a, function()
        print(i)
    end
    )
 
end
 
 
for _, v in ipairs(a) do
    v()
end

Lua打印结果为1 2 3

 

差异在于, C#和Golang将变量捕获到闭包内时, 均使用引用方式, 即当最后开始调用使用变量时, 由于变量已经结束循环, 所以是最终值

但是Lua捕获方式是值捕获, 因此比较容易理解, 是多少就是多少

posted on 2015-09-23 18:31 战魂小筑 阅读(3796) 评论(2)  编辑 收藏 引用 所属分类: 脚本技术Golang

评论

# re: Golang, Lua, C#闭包变量捕获差异 2015-09-24 09:52 马克思
把Lua代码循环部分改一改,也能打印出三个同样的值:
a = {}

local i = 1
while i <= 3 do
table.insert( a, function()
print(i)
end
)
i = i + 1
end


for _, v in ipairs(a) do
v()
end  回复  更多评论
  

# re: Golang, Lua, C#闭包变量捕获差异 2015-09-28 16:45 vv
你的理解完全是错的,C# Golang 和 Lua 闭包都是捕获引用的。
问题在于循环变量 i 变量的作用域
lua 是只在循环体内有效,上一次循环体执行跟下次的 i 是不同的
C# Golang 的 i 作用域包括整个循环条件+循环体,是循环体的外层,上一次循环体执行跟下次的 i 是同一个变量
想要验证的话 看看 for i=1,4 do print(i);i=i+1; end 类似的语句在各个语言里会打印几行

一般执行这种的时候,C# Golang 会在循环体内再定义一个变量让他等于 i 再把这个变量传给闭包
拿这种来考人一般是 javascript ,因为 js 只有函数级作用域,所以循环体内再定义一个变量也是没用的


只有 java 的变量捕获才是值捕获,java闭包所绑定的本地变量必须使用final修饰符

  回复  更多评论
  


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理