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

I am writing what is essentially a chat program. I want to include some special irc style commands in it and I just can't seem to conceptualize how to structure the program. I'm wondering if people could help me out from a high level perspective. I'm not looking for code, just ideas on how to best proceed.

My best attempt is to have a Command struct like below:

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
}

and then have a slice of Commands and just iterate over that every time I receive a message from the client. If the received data matches the regex then have the reflect (I think this will work) package call "function". For some reason, I feel like there has to be a better way. I'm learning to code Go on my own and don't have resources available to me to bounce ideas off of. I would very much appreciate your thoughts on this.

First off, you don't need to use reflect. You can have the Command struct contain a member with a func type.

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 `.*`
}

Then you can add commands with a function of the appropriate signature:

cmd := Command{name: "foo",f: func(text string){fmt.Println(text)}}

it doesn't have to have exactly that signature. You can have it accept a connection or whatever. You also don't have to inline the function definition, you can reference any function you want that has the appropriate signature.

In IRC style commands usually a command line looks like this:

/cmd [param1] [param2] ... [paramn]

When such a command is received, you can split it using strings.Split() to get the parts or tokens of the command. By this you will have the first token identifying the command.

You can build a map[string]Command map where you map from text commands to their Command structure. In this map you can get commands by simply indexing the map, e.g.:

cmdMap := make(map[string]Command)
// Populate map

textCmd := "/help"
cmd := cmdMap[textCmd]

If you want to have command aliases (e.g. you want /help and /h and /? all to do the same), you can store the list of aliases for each command and when you build the cmdMap, also add entries for all aliases to point to the same Command structure, in which case you should define it like this:

cmdMap := make(map[string]*Command)

helpCmd := &Command{...} // Create help command
cmdMap["/help"] = helpCmd
cmdMap["/h"] = helpCmd
cmdMap["/?"] = helpCmd

Note: you could also strip off the leading slash '/' and just use the rest of the command ("help", "h" and "?" in this case) to init your map, it's up to you.

Also you don't have to store the name of the function, functions in Go are values so you can have a function field in your Command struct and then you can call that function without reflection. For example:

func DoSomething() {
    fmt.Println("Doing something...")
}

var someFv = DoSomething

// And now you can do:
someFv()

See Function types and Function literals in the Go Language Specification.