How to avoid long switch-case statement in Go
I'm writing a chatbot in Go and wondering how I can avoid a long switch-case statement like this:
switch {
// @bot search me HMAC
case strings.Contains(message, "search me"):
query := strings.Split(message, "search me ")[1]
return webSearch(query), "html"
// @bot thesaurus me challenge
case strings.Contains(message, "thesaurus me"):
query := strings.Split(message, "thesaurus me ")[1]
return synonyms(query), "html"
Should I define these handlers each in a separate package or should I just use structs and interfaces? What method will allow me to have a good structure, avoid the switch case, and allow external developers to make it easier to create handlers?
I think packages would be the best choice, but I'm not sure how to register handlers with the main bot. Nice to appreciate the example.
source to share
You can use map[string]command
similar to how the package net/http
registers handlers. Something similar to this:
https://play.golang.org/p/9YzHyLodAQ
package main
import (
"fmt"
"errors"
)
type BotFunc func(string) (string, error)
type BotMap map[string]BotFunc
var Bot = BotMap{}
func (b BotMap) RegisterCommand(command string, f BotFunc) error {
if _, exists := b[command]; exists {
return errors.New("command already exists")
}
b[command] = f
return nil
}
func (b BotMap) Execute(statement string) (string, error) {
// parse out command and query however you choose (not this way obviously)
command := statement[:9]
query := statement[10:]
return b.ExecuteQuery(command, query)
}
func (b BotMap) ExecuteQuery(command, query string) (string, error) {
if com, exists := b[command]; exists {
return com(query)
}
return "", errors.New("command doesn't exist")
}
func main() {
err := Bot.RegisterCommand("search me", func(query string) (string, error) {
fmt.Println("search", query)
return "searched", nil
})
if err != nil {
fmt.Println(err)
return
}
err = Bot.RegisterCommand("thesaurus me", func(query string) (string, error) {
fmt.Println("thesaurus", query)
return "thesaurused", nil
})
if err != nil {
fmt.Println(err)
return
}
result, err := Bot.Execute("search me please")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(result)
}
Obviously there are many disadvantages here, but this is the main idea.
source to share