Golang函数和函数变量语义

Dan*_*ams 14 go

为什么我不能将递归函数定义为变量?我似乎能够定义任意函数,除非它们递归.

这是合法的:

func f(i int) int {
    if i == 0 {
        return 1
    }
    return i * f(i-1)
}

func main() {
    fmt.Println(f(2))
}
Run Code Online (Sandbox Code Playgroud)

这是非法的:

var f func(int) int = func(i int) int {
    if i == 0 {
        return 1
    }
    return i * f(i-1)
}

func main() {
    fmt.Println(f(2))
}
Run Code Online (Sandbox Code Playgroud)

这是合法的,我猜这只是因为你可以在初始化后找出f:

func main() {
    var f *func(int) int;
    t := func(i int) int {
        if i == 0 {
            return 1
        }
        return i * (*f)(i-1)
    }
    f = &t
    fmt.Println((*f)(2))
}
Run Code Online (Sandbox Code Playgroud)

所以看起来它归结为功能和函数类型的变量声明被区别对待,尽管从阅读文档我不希望是这种情况.我是否错过了详细说明此文档的部分内容?

我希望非法案件能够正常运作,因为它适用于其他语言.像在JavaScript中一样:

(function () {
  var f = function (i) {
    if (i == 0) {
      return 1;
    }
    return i * f(i - 1);
  };

  console.log(f(2));
})();
Run Code Online (Sandbox Code Playgroud)

Tim*_*per 31

以下代码将是您所描述的首选方式.请注意,您不必创建其他变量,也没有指向函数的指针:

package main

import "fmt"

func main() {
    var f func(int) int
    f = func(i int) int {
        if i == 0 {
            return 1
        }
        return i * f(i-1)
    }
    fmt.Println(f(2))
}
Run Code Online (Sandbox Code Playgroud)

  • @DanielWilliams:来自[spec](https://golang.org/ref/spec#Declarations_and_scope):*在函数内声明的常量或变量标识符的范围从ConstSpec或VarSpec的末尾开始(简称ShortVarDecl)变量声明)并在最内层包含块的末尾结束.*这意味着`f`identifier在完全定义值之前无效.这就是为什么你不能在Go中用JavaScript做的事情. (3认同)