Function 函数重写

Function 函数重写,function,go,Function,Go,我在围棋中发现了一些有趣的东西。假设我的包名是mypkg,在mypkg中,我有两个函数: package mypkg func MyFunc0(){ //... } var MyFunc1 = func(){ //... } 现在,在我的main软件包中,可以覆盖MyFunc1,如下所示: mypkg.MyFunc1 = func(){ // new logic } 但是,不可能以相同的方式重写MyFunc0。因此,现在提出了一个问题。声明函数的两种方法之间有什么区别?

我在围棋中发现了一些有趣的东西。假设我的包名是
mypkg
,在
mypkg
中,我有两个函数:

package mypkg
func MyFunc0(){
    //...
}
var MyFunc1 = func(){
    //...
}
现在,在我的
main
软件包中,可以覆盖
MyFunc1
,如下所示:

mypkg.MyFunc1 = func(){
   // new logic
}

但是,不可能以相同的方式重写
MyFunc0
。因此,现在提出了一个问题。声明函数的两种方法之间有什么区别?这种行为差异是有意的吗?

MyFunc0
是函数声明()

MyFunc1
不是函数声明。它是func类型的变量()(请参见)。它有一个初始值,但可以更改为保存不同的值/函数(只要函数签名匹配)。

我正在学习围棋语言(和英语:p),围棋之旅中有一个exercie:Fibonacci闭包

()

结果是: 0 1. 1. 2. 3. 5. 8. 13 21 三十四

主要功能是:

func main() {
    f := fibonacci()
    for i := 0; i < 10; i++ {
        fmt.Println(f())
    }
}
但是我不想在对f()的heach调用中询问是否是第一个或第二个调用(
if I==0 | | I==1
)。结果是功能自动覆盖:

type doFibonacci func(*doFibonacci) int

func fibonacci() func() int {
    antant := 0
    ant := 1
    i := 0
    doFibo := doFibonacci(func(ptrDo *doFibonacci) int {
        var result int
        if i == 0 || i == 1 {
            result = i
            i++
            return result
        }
        *ptrDo = func(ptrDo *doFibonacci) int {
            var result int
            result = antant + ant
            antant = ant
            ant = result
            return result
        }
        return (*ptrDo)(ptrDo)
    })
    return func() int {
        return doFibo(&doFibo)
    }
}

我为我的英语道歉。

如此有效地说,除了被重写的可能性之外,这两种编写函数的方法之间有什么显著的区别吗?除非有充分的理由不这样做,否则您应该始终使用函数声明(如
MyFunc0
)。它更容易阅读,也不会以令人惊讶的方式改变。老实说,我不确定是否有任何差异。我猜链接器将无法从生成的exe文件中删除var中的函数,即使它未被使用。为什么?函数覆盖是邪恶的吗?谢谢@kostya。还想知道其中一个函数是否比另一个更有效,或者消耗的内存更少?静态函数可以以可变函数文本(即包含函数的变量)无法实现的方式进行优化。例如,可以内联静态函数。虽然Go绝对支持函数文本,但最好只在有特定目标的情况下使用它们。它不是“覆盖”,就像
x=1
是“覆盖”
x
一样。这是围棋中的作业。(在其他语言中,如ML,它是重写的,但是
x=1
在ML中也是重写的。)您没有重写任何内容
MyFunc1
是一个变量,您只需更改它即可。这就是变量的作用,它们是不同的。否则它们将是常量。(事实上,一个变量可以保存一个函数,您可以使用该变量调用该函数,而无需任何特殊语法,这与此无关;例如,这只是与C函数指针的语法差异。)我实际上将它用作Java中的抽象方法。我提供了基本的行为,并且希望客户机可以根据自己的喜好用更具体的行为覆盖默认行为。因为我希望库是抽象的,对实现细节一无所知。请原谅我的话,我来自爪哇,我的大脑深受影响。这样使用它是错误的吗?使用接口(非常类似于Java)可以更容易地实现这一点。我认为
doFibonacci
是一个类型别名。
type doFibonacci func(*doFibonacci) int

func fibonacci() func() int {
    antant := 0
    ant := 1
    i := 0
    doFibo := doFibonacci(func(ptrDo *doFibonacci) int {
        var result int
        if i == 0 || i == 1 {
            result = i
            i++
            return result
        }
        *ptrDo = func(ptrDo *doFibonacci) int {
            var result int
            result = antant + ant
            antant = ant
            ant = result
            return result
        }
        return (*ptrDo)(ptrDo)
    })
    return func() int {
        return doFibo(&doFibo)
    }
}