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

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

问题描述

我有一个名为seeder的软件包:

  package seeder 

importfmt

func MyFunc1(){
fmt.Println(我是Masood)
}

func MyFunc2(){
fmt .Println(我是程序员)
}

func MyFunc3(){
fmt.Println(我想买车)
}

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

  package main 

import./seeder

func main(){
for k:= 1; k <= 3; k ++ {
seeder.MyFunc1()//这会调用MyFunc1三次


code $ pre

我想要这样的东西:

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




 我是马苏德
我是程序员
我想买车


EDIT1
在这个例子中,parentKey是一个字符串var,它在循环中发生变化

 对于parentKey,_:=范围uRLSjson { 
pppp:= seeder +。 + strings.ToUpper(parentKey)
gorilla.HandleFunc(/,pppp).Name(parentKey)
}

但GC表示:


不使用选择器的包装播种器的使用



解决方案

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



使用函数注册表



如果您在调用它们之前构建函数注册表,则只能执行它:

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

输出(在 Go Playground 上试用):

  Hello MyFunc1 
Hello MyFunc2
Hello MyFunc3

手动路由



类似于注册表,正在检查名称并手动路由到函数,例如:

  func callByName(name string){
开关名称{
caseMyFunc1:
MyFunc2()
caseMyFunc2:
MyFunc2()
caseMyFunc3:
MyFunc3()
默认值:
panic(未知函数名称)
}
}

使用它:

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

去游乐场试试这个。



注意:如果您想在 callByName() helper中调用由其名称标识的函数,则由您决定函数,或者您可以选择返回一个函数值(类型为 func()),并在调用者的地方调用它。



将函数转换为方法



还要注意,如果你的函数实际上是某种类型的方法,你可以不用一个注册表。使用反射,您可以按名称获取方法: Value.MethodByName( ) 。您还可以使用 Value获取/枚举所有方法,而无需知道其名称。 NumMethod() Value.Method() (也参见 Type.NumMethod() Type.Method()如果你需要方法的名字或者它的参数类型)。

这是可以做到的:

  type MyType int 
$ b func(m MyType)MyFunc1(){
fmt.Println(Hello MyFunc1)

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

输出是一样的。试试去游乐场


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 var which changes 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 tools 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

You can only do it if you 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天全站免登陆