如何避免Go中的长switch case语句

如何避免Go中的长switch case语句,go,Go,我正在用Go写一个聊天机器人,想知道如何避免类似于下面这句的长切换案例声明: 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

我正在用Go写一个聊天机器人,想知道如何避免类似于下面这句的长切换案例声明:

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"
我应该在单独的包中分别定义这些处理程序,还是只使用结构和接口?哪种方法可以让我拥有一个好的结构,避免切换情况,让外部开发人员更容易地创建处理程序


我认为包是一个更好的选择,但我不确定如何向主bot注册处理程序。请举个例子。

您可以使用类似于
net/http
包注册处理程序的
map[string]命令。类似于此:


显然,这里缺少很多检查,但这是基本的想法。

单独的包可能有些过分,但是如果您希望其他开发人员在不修改代码的情况下创建处理程序,switch语句将不起作用-它是用所有可用选项硬编码的。你想要一个映射之类的东西——以标准库的HTTP mux代码为例。长switch语句有什么问题?这就是switch的用途,@Volker对于其他开发人员来说它不是动态的。为什么不动态地生成switch语句呢
case一些布尔值,使得消息位于dict的键列表中:在该dict中查找查询或执行任何操作,然后执行它;完成
。然后有一些函数,开发者可以在其中注册代码,从而将它们的处理程序或任何东西添加到groovy dict中。我希望每个处理程序都有一个用于匹配的正则表达式,一个用于帮助的描述/用法,以及一个要执行的函数。无法想出一个不需要重复的方法,例如在Handler struct和switch case中都使用“search me”来执行正确的函数。谢谢,这很有帮助。然而,我不确定我是否理解如何使用正则表达式来实现这一点。我使用命名捕获来获取用户的输入。有什么想法吗?这是一个独立的问题,完全取决于你如何定义你的命令结构。如果你还没有,坐下来试着完全定义一个命令是如何构造的,这将帮助你确定如何解析它。它们实际上是两个独立的问题。换一种说法。这里的礼仪要求每个帖子应该有一个问题。考虑到您对regex的关注范围不同,这确实是一个不同的问题。另外,我在答案中添加了一些修饰语。@Maklaus plus,解析命令和查询所需的答案不仅限于Go,它是一个更广泛的问题。它将受益于在自己的问题中使用不同的标签来定位正确的受众。用“
go
标记某事物”可能更能减少看到问题的人的数量。。。
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)
}