Go语言的编译器如何处理嵌套函数?

huangapple go评论88阅读模式
英文:

How does Go's compiler treat nested functions?

问题

在Go语言中,嵌套函数的处理方式是将其转换为另一个函数并放置在代码外部,而不是在每次调用父函数时重新创建。因此,编译器会将嵌套函数提升到外部作用域,并在需要时进行调用。

对于你提供的示例代码:

func FuncA() int {
    a := 0
    funcB := func(_a int) int {
        return _a
    }
    return funcB(a)
}

编译后的函数会类似下面的形式:

func FuncA() int {
    a := 0
    return _funcB(a)
}

func _funcB(_a int) int {
    return _a
}

因此,嵌套函数funcB会被提升为外部函数_funcB,并在FuncA中进行调用。每次调用FuncA时,并不会重新创建_funcB,而是直接调用已经存在的函数。

英文:

When writing a nested function in Go, how does the compiler treat it? Is it turned into another function and put outside the code, or does it get re-created anytime the parent function is called?

For example:

func FuncA() int {
    a := 0
    funcB := func(_a int) int {
        return _a
    }
    return funcB(a)
}

Is this function compiled as follows?

func FuncA() int {
    a := 0
    return _funcB(a)
}
func _funcB(_a int) int {
    return _a
}

Or is it compiled exactly as written which means that new memory is allocated for the definition of funcB anytime FuncA is called?

答案1

得分: 2

嵌套函数被编译为闭包。嵌套函数从封闭作用域中使用的所有变量都被放在堆上,并传递给嵌套函数。在下面的代码片段中:

func FuncA() int {
    a := 0
    funcB := func() int {
        return a
    }
    return funcB()
}

编译后的代码等价于:

type closureB struct {
   a int
}

func FuncA() int {
  c := new(closureB)
  c.a = 0
  return funcB(c)
}

func funcB(c *closureB) int {
  return c.a
}

具体细节取决于运行时和编译器的实现。

英文:

Nested functions are compiled once as closures. All the variables that the nested function uses from the enclosing scope are put on the heap, and passed to the nested function. In the following snippet:

 func FuncA() int {
    a := 0
    funcB := func() int {
        return a
    }
    return funcB()
}

The compiled code is equivalent to:

type closureB struct {
   a int
}

func FuncA() int {
  c:=new(closureB)
  c.a=0
  return funcB(c)
}

func funcB(c *closureB) int {
  return c.a
}

Exact details depend on the runtime and compiler implementation.

答案2

得分: 1

嵌套函数只会被编译一次。

因为FuncB没有引用外部作用域的变量,所以FuncA不会分配堆内存。

如果FuncB引用了外部作用域的变量,那么这些变量将会在堆上分配内存。函数本身只会被编译一次。

英文:

Nested functions are compiled once.

Because FuncB does not close over variables in the surrounding scope, FuncA does not allocate heap memory.

If FuncB closed over any variables in the surrounding scope, then those variables will be allocated on the heap. The function itself is compiled once.

huangapple
  • 本文由 发表于 2022年11月28日 11:01:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/74595554.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定