如何检查函数是否存在

时间:2013-12-27 10:29:42

标签: go

有没有办法检查Go中是否存在func?

在PHP中我可能会做类似

的事情
if(function_exists('someFunction')) {
    //...
}

但是我还没有弄清楚如何在Go

中做到这一点

对此的任何帮助都将受到极大的欢迎。

4 个答案:

答案 0 :(得分:6)

关于你想要做什么的更多背景会有所帮助。 正如您在自己的注释中所述,如果您尝试调用函数,则在编译时进行Go检查(如果函数存在),大多数情况下都是。

我想到的一个例外是,当您使用interface{}并且想要在调用方法之前检查方法是否存在时。为此,您可以使用类型检查。

示例:

package main

import "fmt"

// a simple Greeter struct
// with a Hello() method defined
type Greeter struct {
    Name string 
}
func (m *Greeter) Hello() string {
    return "hello " + m.Name
}

var x interface{}

func main() {
    x = Greeter {Name:"Paolo"} // x is a interface{}
    g,ok := x.(Greeter) // we have to check that x is a Greeter...
    if ok {
        fmt.Println(g.Hello()) // ...before being able to call Hello()
    }
} 

我能想到的另一个场景是你正在为Go创建自己的工具,需要在编译之前解析go文件。如果是这样,Go会为parser package

提供帮助

答案 1 :(得分:2)

没有办法做到这一点(并且为了好!)。原因是Go是一种编译语言,并且不支持可加载模块(至少),因此函数不能在运行时来去,因此无论顶级函数是否存在,您都知道定义:给定源文件import包含感兴趣的函数 1 的包,该函数在此源文件中可见。或者此函数在此源文件所属的同一个包中声明,因此它也可用。在所有其他情况下,该功能不可用。请注意,函数可能在程序中编译,但在编译时仍然在给定的源文件中不可见,因此在Go中不存在可见性的整体定义。

另一方面,你可能需要一些普遍性。 Go中的一般性是通过interfaces实现的。您可以定义一个接口,然后需要一个类型来实现它。检查类型是否实现了接口是通过a neat trick完成的。


1 没有将该模块重命名为空,但我们现在暂不触及。

答案 2 :(得分:1)

提供的东西是接口值,键入assert,如下所示:

if Aer, ok := thing.(interface{MethodA()}); ok { 
  Aer.MethodA() 
} 

如果事物是​​结构,请首先将其分配给接口变量, 因为类型断言仅适用于接口值。

定义命名接口而不使用 随机数,但是对于像这样的简单情况,这是不值得的。

答案 3 :(得分:0)

这听起来很像XY problem。请告诉你要做什么。据我所知,这是你不能像在PHP中那样做的事情。

但是,您可以创建一个功能名称为键的地图。手动添加函数或通过在编译之前或运行时解析源文件来生成内容。解析源代码似乎是一个肮脏的黑客。