duanjia1870
2017-06-28 20:50
浏览 337
已采纳

如何避免在Go中使用长的switch-case语句

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.

图片转代码服务由CSDN问答提供 功能建议

我正在用Go编写聊天机器人,想知道如何避免类似这样的冗长的switch-case语句 一个:

 开关{
 
 // @bot搜索我HMAC 
case字符串。包含(消息,“搜索我”):
查询:=字符串。 拆分(消息,“搜索我”)[1] 
返回webSearch(查询),“ html” 
 
 // @机器人同义词库挑战
大小写字符串。包含(消息,“同义词库我”):
  query:= strings.Split(message,“ thesaurus me”)[1] 
返回同义词(query),“ html” 
   
 
 

我应该定义这些处理程序 每个都放在单独的程序包中,还是应该只使用结构和接口? 哪种方法可以使我拥有良好的结构,避免切换情况,并让外部开发人员更轻松地创建处理程序?

我认为软件包将是更好的选择,但我不确定如何 向主机器人注册处理程序。 将不胜感激。

  • 写回答
  • 好问题 提建议
  • 追加酬金
  • 关注问题
  • 邀请回答

1条回答 默认 最新

  • drkrsx3135168 2017-06-28 21:27
    最佳回答

    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.

    评论
    解决 无用
    打赏 举报

相关推荐 更多相似问题