我正在编写一个具有irc样式命令的聊天应用程序。构建程序以处理这些命令的最佳方法是什么?

时间:2015-04-08 04:45:25

标签: go

我正在撰写本质上是聊天程序的内容。我想在其中包含一些特殊的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并且没有资源可以让我反省意见。我非常感谢你对此的看法。

2 个答案:

答案 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 typesFunction 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)}}

它不必具有该签名。你可以让它接受连接或其他什么。您也不必内联函数定义,您可以引用任何具有相应签名的函数。