在golang中,如果不使用反射,如何优雅地动态调用一个方法呢?

huangapple go评论76阅读模式
英文:

How do I elegantly call a method dynamically in golang without using reflection?

问题

我正在使用反射来完成这个任务:

method_name := CommandMap[command]
thing := reflect.ValueOf(self).MethodByName(method_name)
thing_s := fmt.Sprintf("%s", thing)
if thing_s == "<invalid reflect.Value>" {
	self.writeMessage(550, "not allowed")
} else {
	thing.Call([]reflect.Value{})
}

但是肯定有更好的方法。上述代码的目的是摆脱以下的代码块:

if command == "this" {
	runThis()
} else if command == "that" {
	runThat()
} 等等。

我不想要一个庞大的 if-else 树。这是一个 FTP 服务器的代码,链接在这里:http://github.com/andrewarrow/paradise_ftp,我需要处理大约15个命令,如 "USER"、"PASS" 和 "QUIT" 等等。我希望每个命令都调用一个类似 "handleUser" 或 "handlePass" 的方法。但是使用反射是一个不好的主意,因为它太慢了。

英文:

I'm using reflection to do this:

		method_name := CommandMap[command]
	thing := reflect.ValueOf(self).MethodByName(method_name)
	thing_s := fmt.Sprintf(&quot;%s&quot;, thing)
	if thing_s == &quot;&lt;invalid reflect.Value&gt;&quot; {
		self.writeMessage(550, &quot;not allowed&quot;)
	} else {
		thing.Call([]reflect.Value{})
	}

but there must be a better way. The point of the above code was to get rid of:

if command == &quot;this&quot; {
  runThis()
} else if command == &quot;that&quot; {
  runThat()
} etc. etc.

I want to not have a big if else tree. This is an ftp server http://github.com/andrewarrow/paradise_ftp and I need to handle 15 or so commands like "USER" and "PASS" and "QUIT" etc. etc. I want each one to call a method like "handleUser" or "handlePass". But using reflection is a bad idea. It's too slow.

答案1

得分: 7

根据您提供的代码示例,最好使用字符串到函数的映射。示例如下:

func MakeCommandMap() map[string]func(*Paradise) {
    m := map[string]func(*Paradise){
        "USER": (*Paradise).HandleUser,
        "PASS": (*Paradise).HandlePass,
    }
    // ...
    return m
}

// 调用函数:
name := "USER"
if fn := m[name]; fn != nil {
    fn(self) // 这里的self是*Paradise类型
}

请注意,这只是一个示例,您可能需要根据您的实际需求进行适当的修改。

英文:

From your linked use case, it appears that having a map of strings to functions will work best. Example:

func MakeCommandMap() map[string]func(*Paradise) {
    m := map[string]func(*Paradise){
	    &quot;USER&quot;: (*Paradise).HandleUser,
		&quot;PASS&quot;: (*Paradise).HandlePass,
    }
    // ...
	return m
}

Calling the functions:

name := &quot;USER&quot;
if fn := m[name]; fn != nil {
    fn(self) // where self is *Paradise
}

huangapple
  • 本文由 发表于 2016年3月14日 05:35:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/35976162.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定