I'm writing a chat bot in Go and wondering how can I avoid a long switch-case statement similar to this one:
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 those handlers each in a separate package or should I just use structs and interfaces? Which method will allow me to have a good structure, avoid switch-case and let external developers to easier create handlers?
I think packages will be a better choice but I'm not sure how to register the handlers with the main bot. Would appreciate an example.
You could use a map[string]command
similar to how the net/http
package registers handlers. Something akin 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's a lot of checks missing here, but this is the basic idea.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With