我正在撰写本质上是聊天程序的内容。我想在其中包含一些特殊的irc样式命令,我似乎无法概念化如何构建程序。我想知道人们是否可以从高层次的角度帮助我。我不是在寻找代码,而只是关于如何最好地进行的想法。
我最好的尝试是拥有如下所示的Command结构:
type Command struct {
name string // the name of the command
function string // the function that will be called upon match
help string // the help message for the command
regex string // the regex pattern that will run the command
}
然后有一段命令,每次从客户端收到消息时都会迭代它。如果收到的数据与正则表达式匹配,则反映(我认为这将起作用)包调用"功能"。出于某种原因,我觉得必须有更好的方法。我正在学习自己的代码Go并且没有资源可以让我反省意见。我非常感谢你对此的看法。
答案 0 :(得分:1)
在IRC样式命令中,命令行通常如下所示:
/cmd [param1] [param2] ... [paramn]
收到此类命令后,您可以使用strings.Split()
拆分它以获取命令的部分或标记。通过这个,您将拥有识别命令的第一个标记。
您可以构建一个map[string]Command
地图,您可以在其中将文本命令映射到其Command
结构。在此地图中,您可以通过简单地索引地图来获取命令,例如:
cmdMap := make(map[string]Command)
// Populate map
textCmd := "/help"
cmd := cmdMap[textCmd]
如果您想拥有命令别名(例如,您希望/help
和/h
以及/?
所有人都这样做),您可以存储每个命令的别名列表以及何时您构建cmdMap
,还为所有别名添加条目以指向相同的Command
结构,在这种情况下,您应该像这样定义:
cmdMap := make(map[string]*Command)
helpCmd := &Command{...} // Create help command
cmdMap["/help"] = helpCmd
cmdMap["/h"] = helpCmd
cmdMap["/?"] = helpCmd
注意:您也可以删除前导斜杠'/'
,并使用命令的其余部分(本例中为"help"
,"h"
和"?"
)来初始化你的地图,取决于你。
此外,您不必存储函数的名称,Go中的函数是值,因此您可以在Command
结构中包含一个函数字段,然后您可以在不反射的情况下调用该函数。例如:
func DoSomething() {
fmt.Println("Doing something...")
}
var someFv = DoSomething
// And now you can do:
someFv()
请参阅Go语言规范中的Function types和Function literals。
答案 1 :(得分:0)
首先,您不需要使用反射。您可以让Command
结构包含具有func类型的成员。
type Command struct {
name string // the name of the command
f func(string) // the function that will be called upon match
help string // the help message for the command
regex regexp.Regexp // the regex pattern that will run the command
}
func processMessage(text string){
for _,cmd := range(allCmds){
if cmd.regex.MatchString(text){
cmd.f(text)
return
}
}
defaultAction(text) //or just add a catch-all with a regex of `.*`
}
然后,您可以添加具有相应签名功能的命令:
cmd := Command{name: "foo",f: func(text string){fmt.Println(text)}}
它不必具有该签名。你可以让它接受连接或其他什么。您也不必内联函数定义,您可以引用任何具有相应签名的函数。