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)
}
}