具有特殊前缀/后缀的调用函数 [英] Call functions with special prefix/suffix

查看:22
本文介绍了具有特殊前缀/后缀的调用函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个名为seeder"的包:

包播种机导入fmt"func MyFunc1() {fmt.Println("我是马苏德")}func MyFunc2() {fmt.Println("我是程序员")}func MyFunc3() {fmt.Println("我要买车")}

现在我想调用带有 MyFunc 前缀的所有函数

包主导入./播种机"功能主(){对于 k := 1;k<=3;k++{Seeder.MyFunc1()//这会调用 MyFunc1 3 次}}

我想要这样的东西:

for k := 1;k<=3;k++{播种机.MyFunc + k()}

和这个输出:

<块引用>

我是马苏德我是电脑程序编制员我想买车

EDIT1:在这个例子中,parentKey 是一个循环变化的字符串变量

for parentKey, _ := range uRLSjson{pppp := 播种机 + "."+ strings.ToUpper(parentKey)gorilla.HandleFunc("/", pppp).Name(parentKey)}

但是 GC 说:

<块引用>

使用没有选择器的包播种器

解决方案

您无法通过函数名称获取函数,而这正是您想要做的.原因是如果 Go 工具可以检测到一个函数没有被显式引用(因此无法访问),它甚至可能不会被编译成可执行的二进制文件.有关详细信息,请参阅拆分客户端/服务器代码.

带有函数注册表

做你想做的一种方法是在调用它们之前构建一个函数注册表":

registry := map[string]func(){"MyFunc1": MyFunc1,"MyFunc2": MyFunc2,"MyFunc3": MyFunc3,}对于 k := 1;k<=3;k++{注册表[fmt.Sprintf("MyFunc%d", k)]()}

输出(在 Go Playground 上试试):

Hello MyFunc1你好 MyFunc2你好我的Func3

手动路由"

与注册表类似的是检查名称并手动路由到函数,例如:

func callByName(name string) {开关名称{案例MyFunc1":MyFunc1()案例MyFunc2":MyFunc2()案例MyFunc3":MyFunc3()默认:恐慌(未知的函数名称")}}

使用:

for k := 1;k<=3;k++{callByName(fmt.Sprintf("MyFunc%d", k))}

Go Playground 上试试这个.

注意: 是否要调用在 callByName() 辅助函数中由其名称标识的函数取决于您,或者您可以选择返回一个函数值(func() 类型)并在调用者的位置调用它.

将函数转化为方法

另请注意,如果您的函数实际上是某种类型的方法,您可以在没有注册表的情况下实现.使用反射,您可以通过名称获取方法:Value.MethodByName().您还可以使用 Value.NumMethod()<在不知道名称的情况下获取/枚举所有方法/code>Value.Method()(如果需要方法的名称或其参数类型,另见 Type.NumMethod()Type.Method()).

这是如何做到的:

type MyType intfunc (m MyType) MyFunc1() {fmt.Println("Hello MyFunc1")}func (m MyType) MyFunc2() {fmt.Println("Hello MyFunc2")}func (m MyType) MyFunc3() {fmt.Println("Hello MyFunc3")}功能主(){v :=reflect.ValueOf(MyType(0))对于 k := 1;k<=3;k++{v.MethodByName(fmt.Sprintf("MyFunc%d", k)).Call(nil)}}

输出是一样的.在 Go Playground 上试试.

I have a package named "seeder":

package seeder

import "fmt"

func MyFunc1() {
    fmt.Println("I am Masood")
}

func MyFunc2() {
    fmt.Println("I am a programmer")
}

func MyFunc3() {
    fmt.Println("I want to buy a car")
}

Now I want to call all functions with MyFunc prefix

package main

import "./seeder"

func main() {
    for k := 1; k <= 3; k++ {
        seeder.MyFunc1() // This calls MyFunc1 three times
    }
}

I want something like this:

for k := 1; k <= 3; k++ {
    seeder.MyFunc + k ()
}

and this output:

I am Masood
I am a programmer
I want to buy a car

EDIT1: In this example, parentKey is a string variable which changed in a loop

for parentKey, _ := range uRLSjson{ 
    pppp := seeder + "." + strings.ToUpper(parentKey)
    gorilla.HandleFunc("/", pppp).Name(parentKey)
}

But GC said:

use of package seeder without selector

解决方案

You can't get a function by its name, and that is what you're trying to do. The reason is that if the Go tool can detect that a function is not referred to explicitly (and thus unreachable), it may not even get compiled into the executable binary. For details see Splitting client/server code.

With a function registry

One way to do what you want is to build a "function registry" prior to calling them:

registry := map[string]func(){
    "MyFunc1": MyFunc1,
    "MyFunc2": MyFunc2,
    "MyFunc3": MyFunc3,
}
for k := 1; k <= 3; k++ {
    registry[fmt.Sprintf("MyFunc%d", k)]()
}

Output (try it on the Go Playground):

Hello MyFunc1
Hello MyFunc2
Hello MyFunc3

Manual "routing"

Similar to the registry is inspecting the name and manually routing to the function, for example:

func callByName(name string) {
    switch name {
    case "MyFunc1":
        MyFunc1()
    case "MyFunc2":
        MyFunc2()
    case "MyFunc3":
        MyFunc3()
    default:
        panic("Unknown function name")
    }
}

Using it:

for k := 1; k <= 3; k++ {
    callByName(fmt.Sprintf("MyFunc%d", k))
}

Try this on the Go Playground.

Note: It's up to you if you want to call the function identified by its name in the callByName() helper function, or you may choose to return a function value (of type func()) and have it called in the caller's place.

Transforming functions to methods

Also note that if your functions would actually be methods of some type, you could do it without a registry. Using reflection, you can get a method by name: Value.MethodByName(). You can also get / enumerate all methods without knowing their names using Value.NumMethod() and Value.Method() (also see Type.NumMethod() and Type.Method() if you need the name of the method or its parameter types).

This is how it could be done:

type MyType int

func (m MyType) MyFunc1() {
    fmt.Println("Hello MyFunc1")
}

func (m MyType) MyFunc2() {
    fmt.Println("Hello MyFunc2")
}

func (m MyType) MyFunc3() {
    fmt.Println("Hello MyFunc3")
}

func main() {
    v := reflect.ValueOf(MyType(0))
    for k := 1; k <= 3; k++ {
        v.MethodByName(fmt.Sprintf("MyFunc%d", k)).Call(nil)
    }
}

Output is the same. Try it on the Go Playground.

这篇关于具有特殊前缀/后缀的调用函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆