为了账号安全,请及时绑定邮箱和手机立即绑定

Golang 在编写函数闭包时会自动将变量分配为参数吗?

Golang 在编写函数闭包时会自动将变量分配为参数吗?

Go
湖上湖 2023-07-10 17:55:02
这是我引用的代码:package mainimport "fmt"func adder() func(int) int {    sum := 0    return func(x int) int {        sum += x        return sum    }}func main() {    pos, neg := adder(), adder()    for i := 0; i < 10; i++ {        fmt.Println(            pos(i),            neg(-2*i),        )    }}以下是运行时的输出:    0 0    1 -2    3 -6    6 -12    10 -20    15 -30    21 -42    28 -56    36 -72    45 -90我不明白函数中的语句x是如何分配的?它似乎没有在函数中的任何地方传递。我也不明白这个变量是如何工作的。每次调用该函数并为其赋值时,不应该重置它吗?returnaddersumadder0
查看完整描述

2 回答

?
蓝山帝景

TA贡献1843条经验 获得超7个赞

Go 以非常典型/标准的方式处理一流的函数和闭包。在这种情况下,调用adder自身:

  1. 创建以 valueint命名的对象。sum0

  2. 返回一个闭包:一个类似函数的东西1,当被调用时,可以访问变量sum

返回的特定类似函数的东西adder(其调用者在普通变量中捕获)是一个带有一个参数的函数。然后你调用它,传递一个参数。这种参数传递没有什么特别之处:它的工作方式与其他地方相同。在类似函数的东西中,使用变量x可以获取调用者传递的值。使用名称sum可以获取捕获的int对象,无论其值是什么。从函数返回后,捕获的内容int仍然被捕获,因此稍后调用相同的类似函数的东西会看到int中的更新sum

通过调用adder两次,您会得到两个略有不同的类似函数的东西:每个都有自己的私有sum. 这两个 privatesum最初都为零。调用您保存了值的类似函数的东西pos可以获得使用其中之一的函数。调用稍微不同的类似函数的东西,你保存了它的值,neg你就可以得到使用另一个函数的函数。


1这个“类似函数的东西”和实际的函数之间没有真正的区别,只是这个特定的类似函数的东西没有可以调用它的名称。这或多或少就是拥有一流功能的含义。


如果您遇到可读性问题......

其原始形式是:

func adder() func(int) int {

    sum := 0

    return func(x int) int {

        sum += x

        return sum

    }

}

让我们用一些类型名称和其他语法更改来重写它,使代码的核心保持不变。首先,让我们起一个名字,意思是func(int) int:


type adderClosure func(int) int

然后我们可以用它来重写adder第一行:


func adder() adderClosure {

    ...

}

现在让我们在加法器中创建一个局部变量来保存我们要返回的函数。为了明确和冗余,我们可以再次使用这种类型:


    var ret adderClosure // not good style: just for illustration

现在让我们通过执行以下操作将该变量分配给我们的闭包:


    sum := 0

    ret = func(x int) int {

        sum += x

        return sum

    }

然后我们可以return ret返回闭包。 这是 Go Playground 上的完整代码。


查看完整回答
反对 回复 2023-07-10
?
汪汪一只猫

TA贡献1898条经验 获得超8个赞

当您分配和时,该sum变量位于两个闭包中。闭包中的是通过添加 1, 2, 3, 4(斐波那契风格)来更新的,而闭包中的是通过在每次循环迭代中减去 2*1, 2*2, 2*3, 2*4 来更新的。posnegsumpossumneg


或者,更详细地说: pos := adder()分配给一个函数,该函数具有从0 开始的pos闭包。然后每当您调用该函数时,它都会相应更新。和任何其他类似的作业也是如此。sumsumpossumneg


以下是一些类似(更简单)的 JavaScript 代码,可在浏览器控制台中运行:


function adder() {

  var sum = 0;

  return function(i) {

    sum += i;

    return sum;

  }

}


var pos = adder();

console.log( pos(1) ); // add 1 to 0 (1)

console.log( pos(2) ); // add 2 to 1 (3)

console.log( pos(3) ); // add 3 to 3 (6)

console.log( pos(4) ); // add 4 to 6 (10)

查看完整回答
反对 回复 2023-07-10
  • 2 回答
  • 0 关注
  • 112 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信