Go:按名称查找函数

Go:按名称查找函数,go,reflection,casting,type-safety,go-reflect,Go,Reflection,Casting,Type Safety,Go Reflect,我不熟悉类型安全,不知道如何执行以下操作 package main func test(){ print("In Test") } func main(){ a := "test" a() } 无法从字符串解析函数。但是,可以将函数指定给变量 a := test a() 您还可以将函数(假设它们都具有相同的签名)放入映射中: var func_map := map[string]func() { "test": test, } a := func_map

我不熟悉类型安全,不知道如何执行以下操作

package main

func test(){
    print("In Test")
}

func main(){
    a := "test"
    a()
}

无法从字符串解析函数。但是,可以将函数指定给变量

a := test
a()
您还可以将函数(假设它们都具有相同的签名)放入映射中:

var func_map :=  map[string]func() {
    "test": test,
}
a := func_map["test"]
a()

OP对第一条评论的回应(太长,无法再发表评论):

  • 函数不是“文字”。“字面意义”有单独的含义
  • 其次,Go的运行时反射没有将字符串映射到函数的查找表。即使是这样,函数也不会链接到二进制文件中,除非通过其他代码链接到。仅在此方法中调用的代码不会以二进制形式出现
  • 第三,手动绘制映射并不难。它提供编译时类型的安全检查以及安全性
  • 这不是你用任何语言都应该做的事情。它就像eval(),您真的不应该使用它,因为它可能非常危险,并导致不可预知的事情发生

  • 他们不是都有相同的签名

    如果他们没有相同的签名,你打算怎么称呼他们?您可以使用
    reflect
    包,但这通常表示您做错了什么


    这不是一种动态语言,有些事情在围棋中无法完成。尽管在大多数语言中,这些都是不应该做的事情。

    没有办法按名称动态查找函数,但我认为值得一提的是原因。基本上,原因是编译器和/或链接器可以消除未使用的函数


    考虑一下,如果您能够按名称获取函数,那么每个导入包中的每个函数(递归地)都必须链接到最终的可执行文件中,即使它从未被使用过,以防有人想按名称查找它。人们已经在抱怨Go二进制文件太大,但这会导致它们变得更大。

    如果你陈述你想要实现的目标,你可能会得到更好的答案,因为反射通常不是最好的方式。但如果函数是类型(是)上的方法,则会有所帮助

    如果您想知道像这样的工具是如何工作的,那么它们解析源代码而不是使用反射


    编辑:

    它们不是都有相同的签名,这是什么意思。我必须首先映射所有函数。这应该是一台电脑而不是笔记本。一定有办法将字符串转换为文本。请参阅我在答案中的评论。在提问之前,你是否阅读过任何Go文档,例如语言规范?你可能有PHP背景吗?请注意,并非PHP的所有功能都是编程语言的好功能。OP在go nuts邮件列表中也提出了这个问题,这是一个很好的主题(+1表示不公平的反对票):您看过go的各种评估包了吗?类似于?嗯,这不是我想要做的。我只是不想查看已经导入/加载且可用的函数列表。这相当于按名称动态获取函数。
    package main
    
    import (
        "fmt"
        "reflect"
    )
    
    type T struct {}
    
    func (T) Add(x, y int) int {
        return x + y
    }
    
    func main() {
        t := reflect.ValueOf(T{})
        m := t.MethodByName("Add")
        args := []reflect.Value{reflect.ValueOf(1), reflect.ValueOf(2)}
        fmt.Println(m.Call(args)[0].Int())
    }