在Go中解析简单的复选框组

时间:2016-03-14 20:51:56

标签: forms text go dry idioms

我在Go中解析一个表单,我经常发现需要将这些复选框组合成如下所示的文本:

[ ] Foo
[x] Bar
[ ] Baz
[x] Bat

其中输出应该是以逗号分隔的列表“BarText,BatText”对应于选中的项目,或者“None”(如果没有选中任何项目)。处理这种情况的好方法是什么?每次重复逻辑似乎都是一个坏主意。

本着YAGNI的精神,没有必要处理可能的未来变化,例如翻译成其他语言(实际上这个例子在目前的情况下极不可能有用)。

效率对于此应用程序并不重要。

编辑:代码如下所示(source):

func handleCheckboxesForm(w http.ResponseWriter, r *http.Request) {
    b := func(name string) string { // helper function for boolean values in the form
        return r.FormValue(name) == "on"
    }

    text := "Header stuff here"

    mytext := ""
    if b("nfpa-alk") {
        mytext += ", alkaline"
    }
    if b("nfpa-acid") {
        mytext += ", acid"
    }
    if b("nfpa-w") {
        mytext += ", reacts violently with water"
    }
    if b("nfpa-alk") || b("nfpa-acid") || b("nfpa-w") {
        text += mytext[2:] + "\n"
    } else {
        text += "none\n"
    }

    // lots of other checkbox groups here

    // do stuff with text
}

2 个答案:

答案 0 :(得分:1)

您的许多重复代码可以进行优化。

您的代码必须至少包含以下"片段":

  1. 从条目名称到条目文本的映射,可以存储在地图中,例如

    var mappings = map[string]string {
        "Foo": "Foo text",
        "Bar": "Bar text",
        "Baz": "Baz text",
        "Bat": "Bat text",
        // ... other mappings
    }
    
  2. 属于一个组的密钥列表,可以存储在一个切片中,例如

    var group1 = []string{"Foo", "Bar", "Baz", "Bat"}
    
  3. 一旦定义了这些,就可以有一个处理组的辅助方法:

    func handleGroup(r *http.Request, group []string) (res string) {
        for _, v := range group {
            if r.FormValue(v) == "on" {
                res := ", " + mappings[v]
            }
        }
        if res == "" {
            return "none\n"
        }
        return res[2:] + "\n"
    }
    

    这就是全部。在此之后,您的处理程序可以很简单:

    func checkboxHandler(w http.ResponseWriter, r *http.Request) {
        // Handle group1:
        res1 := handleGroup(r, group1)
    
        // Handle group2:
        res2 := handleGroup(r, group2)
    }
    

    备注:

    这不是您的要求,但此解决方案非常容易处理翻译:每个翻译都可以拥有自己的mappings地图,而这一切都是。没有别的东西需要改变。

    性能也不是你的顾虑,但追加字符串并不是很有效。如果性能至少是一个问题,您可以通过使用bytes.Buffer

    来改进它,而不会增加复杂性
    func handleGroup(r *http.Request, group []string) string {
        buf := &bytes.Buffer{}
        for _, v := range group {
            if r.FormValue(v) == "on" {
                buf.WriteString(", ")
                buf.WriteString(mappings[v])
            }
        }
        if buf.Len() == 0 {
            return "none\n"
        }
        buf.WriteString("\n")
        return string(buf.Bytes()[2:])
    }
    

答案 1 :(得分:0)

这会将表单值存储到数组中。 然后,它会将数组迭代为一个字符串,并附加","在每个名字的末尾。 然后,它将放在最后"," (2个字节)如果它长于2,否则,打印"无"

or

如果你想迭代,

func(w http.ResponseWriter, r *http.Request) {
    r.ParseMultipartForm(0)
    arr := []string{}
    if r.FormValue("Foo") {
        arr = append(arr, "Foo")
    }
    if r.FormValue("Bar") {
        arr = append(arr, "Bar")
    }
    if r.FormValue("Baz") {
        arr = append(arr, "Baz")
    }
    if r.FormValue("Bat") {
        arr = append(arr, "Bat")
    }
    out := ""
    for _, title := range arr {
        out += title +", "
    }
    if len(out) > 2 {
        out := out[0: len(out)-2]   
    } else {
        out = "None"
    }

    fmt.Println(out)
}