Forms 使用绑定解析数组表单元素

Forms 使用绑定解析数组表单元素,forms,parsing,go,binding,Forms,Parsing,Go,Binding,我试图在go中提交并解析表单,但未能正确解析表单字段。 下面是我正在尝试的代码的摘录 formtest.go: 包干管 import ( "fmt" "log" "net/http" "github.com/codegangsta/negroni" "github.com/davecgh/go-spew/spew" "github.com/julienschmidt/httprouter" "github.com/mholt/bindin

我试图在go中提交并解析表单,但未能正确解析表单字段。 下面是我正在尝试的代码的摘录

formtest.go: 包干管

import (
    "fmt"
    "log"
    "net/http"

    "github.com/codegangsta/negroni"
    "github.com/davecgh/go-spew/spew"
    "github.com/julienschmidt/httprouter"
    "github.com/mholt/binding"
    "gopkg.in/unrolled/render.v1"
)

type FormInfo struct {
    Fields    []string
    Action    string
    PageTitle string
    Id        string
}

func (f *FormInfo) FieldMap(*http.Request) binding.FieldMap {
    return binding.FieldMap{
        &f.Fields: "fields",
        &f.Action: "action",
    }
}

func formtest(
    resp http.ResponseWriter,
    req *http.Request,
    p httprouter.Params) {

    // var ticket Ticket
    info := new(FormInfo)
    tkt := p.ByName("tkt")
    info.PageTitle = tkt
    info.Id = tkt

    if req.Method == "POST" {
        bind_err := binding.Bind(req, info)
        if bind_err.Handle(resp) {
            log.Println("Error decoding form contents")
            return
        }
        spew.Dump(info)
    }

    Render.HTML(resp, http.StatusOK, "formtest", info)
    return
}

var Render *render.Render

func main() {

    router := httprouter.New()

    router.GET("/formtest", formtest)
    router.POST("/formtest", formtest)

    Render = render.New(render.Options{
        Layout:          "layout",
        IndentJSON:      true,
        IndentXML:       true,
        HTMLContentType: "text/html",
        IsDevelopment:   true,
    })

    n := negroni.New(
        negroni.NewRecovery(),
        negroni.NewLogger(),
        negroni.NewStatic(http.Dir("static")),
    )
    n.UseHandler(router)
    n.Run(fmt.Sprintf(":%d", 3000))

}
模板/layout.tmpl:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>{{ .PageTitle }}</title>
    <meta http-equiv="Content-Type" content="text/html;" charset="utf-8">
    <meta charset="UTF-8">
    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
    <link rel="apple-touch-icon" href="/mobile.png" />
    <meta name="viewport" 
          content="initial-scale=1.0,width=device-width,user-scalable=no">
    <meta name="generator" content="Go">
    <link rel="stylesheet" href="/base.css" type="text/css">
  </head>

  <body>

      <div class="mainbody">
        {{ yield }}
      </div>

  </body>

</html>
<h1>{{ .PageTitle }}</h1>

<form action="/formtest/{{ .Id }}" method="POST">

    <div class="details">
      <label>Question 1</label>
      <input type="text" name="fields[0]" value="value 1" />
    </div>

    <div class="details">
      <label>Question 2</label>
      <input type="text" name="fields[1]" value="value 2" />
    </div>

    <div class="details">
      <input type="submit" name="action" value="save" />
    </div>

</form>
(*main.FormInfo)(0xc820066c30)({
 Fields: ([]string) <nil>,
 Action: (string) (len=4) "save",
 PageTitle: (string) "",
 Id: (string) ""
})
Fields: ([]string) <contains two values submitted>,

{{.PageTitle}
{{yield}}
模板/formtest.tmpl:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>{{ .PageTitle }}</title>
    <meta http-equiv="Content-Type" content="text/html;" charset="utf-8">
    <meta charset="UTF-8">
    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
    <link rel="apple-touch-icon" href="/mobile.png" />
    <meta name="viewport" 
          content="initial-scale=1.0,width=device-width,user-scalable=no">
    <meta name="generator" content="Go">
    <link rel="stylesheet" href="/base.css" type="text/css">
  </head>

  <body>

      <div class="mainbody">
        {{ yield }}
      </div>

  </body>

</html>
<h1>{{ .PageTitle }}</h1>

<form action="/formtest/{{ .Id }}" method="POST">

    <div class="details">
      <label>Question 1</label>
      <input type="text" name="fields[0]" value="value 1" />
    </div>

    <div class="details">
      <label>Question 2</label>
      <input type="text" name="fields[1]" value="value 2" />
    </div>

    <div class="details">
      <input type="submit" name="action" value="save" />
    </div>

</form>
(*main.FormInfo)(0xc820066c30)({
 Fields: ([]string) <nil>,
 Action: (string) (len=4) "save",
 PageTitle: (string) "",
 Id: (string) ""
})
Fields: ([]string) <contains two values submitted>,
{{.PageTitle}
问题1
问题2
程序:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>{{ .PageTitle }}</title>
    <meta http-equiv="Content-Type" content="text/html;" charset="utf-8">
    <meta charset="UTF-8">
    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
    <link rel="apple-touch-icon" href="/mobile.png" />
    <meta name="viewport" 
          content="initial-scale=1.0,width=device-width,user-scalable=no">
    <meta name="generator" content="Go">
    <link rel="stylesheet" href="/base.css" type="text/css">
  </head>

  <body>

      <div class="mainbody">
        {{ yield }}
      </div>

  </body>

</html>
<h1>{{ .PageTitle }}</h1>

<form action="/formtest/{{ .Id }}" method="POST">

    <div class="details">
      <label>Question 1</label>
      <input type="text" name="fields[0]" value="value 1" />
    </div>

    <div class="details">
      <label>Question 2</label>
      <input type="text" name="fields[1]" value="value 2" />
    </div>

    <div class="details">
      <input type="submit" name="action" value="save" />
    </div>

</form>
(*main.FormInfo)(0xc820066c30)({
 Fields: ([]string) <nil>,
 Action: (string) (len=4) "save",
 PageTitle: (string) "",
 Id: (string) ""
})
Fields: ([]string) <contains two values submitted>,
  • 运行formtest.go
  • 打开浏览器并转到
  • 提交表格
  • 检查控制台中的日志
  • 观察:

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <title>{{ .PageTitle }}</title>
        <meta http-equiv="Content-Type" content="text/html;" charset="utf-8">
        <meta charset="UTF-8">
        <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
        <link rel="apple-touch-icon" href="/mobile.png" />
        <meta name="viewport" 
              content="initial-scale=1.0,width=device-width,user-scalable=no">
        <meta name="generator" content="Go">
        <link rel="stylesheet" href="/base.css" type="text/css">
      </head>
    
      <body>
    
          <div class="mainbody">
            {{ yield }}
          </div>
    
      </body>
    
    </html>
    
    <h1>{{ .PageTitle }}</h1>
    
    <form action="/formtest/{{ .Id }}" method="POST">
    
        <div class="details">
          <label>Question 1</label>
          <input type="text" name="fields[0]" value="value 1" />
        </div>
    
        <div class="details">
          <label>Question 2</label>
          <input type="text" name="fields[1]" value="value 2" />
        </div>
    
        <div class="details">
          <input type="submit" name="action" value="save" />
        </div>
    
    </form>
    
    (*main.FormInfo)(0xc820066c30)({
     Fields: ([]string) <nil>,
     Action: (string) (len=4) "save",
     PageTitle: (string) "",
     Id: (string) ""
    })
    
    Fields: ([]string) <contains two values submitted>,
    
    (*main.FormInfo)(0xc820066c30)({
    字段:([]字符串),
    操作:(字符串)(len=4)“保存”,
    PageTitle:(字符串)“,
    Id:(字符串)”
    })
    
    期望值:

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <title>{{ .PageTitle }}</title>
        <meta http-equiv="Content-Type" content="text/html;" charset="utf-8">
        <meta charset="UTF-8">
        <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
        <link rel="apple-touch-icon" href="/mobile.png" />
        <meta name="viewport" 
              content="initial-scale=1.0,width=device-width,user-scalable=no">
        <meta name="generator" content="Go">
        <link rel="stylesheet" href="/base.css" type="text/css">
      </head>
    
      <body>
    
          <div class="mainbody">
            {{ yield }}
          </div>
    
      </body>
    
    </html>
    
    <h1>{{ .PageTitle }}</h1>
    
    <form action="/formtest/{{ .Id }}" method="POST">
    
        <div class="details">
          <label>Question 1</label>
          <input type="text" name="fields[0]" value="value 1" />
        </div>
    
        <div class="details">
          <label>Question 2</label>
          <input type="text" name="fields[1]" value="value 2" />
        </div>
    
        <div class="details">
          <input type="submit" name="action" value="save" />
        </div>
    
    </form>
    
    (*main.FormInfo)(0xc820066c30)({
     Fields: ([]string) <nil>,
     Action: (string) (len=4) "save",
     PageTitle: (string) "",
     Id: (string) ""
    })
    
    Fields: ([]string) <contains two values submitted>,
    
    字段:([]字符串),
    
    但是当我试图打印字段的内容时,它是零。
    我做错了什么?

    绑定不起作用。表单的字段-name=“fields[1]”和 name=“字段[0]”相互独立,因此对于每个字段,您的结构都应该包含自己的字段:

    type FormInfo struct {
        Fields1   string
        Fields2   string
        Action    string
        PageTitle string
        Id        string
    }
    
    分别在处理程序中:

    ...
    &f.Fields1: "fields[0]",
    &f.Fields2: "fields[1]",
    &f.Action:  "action",
    ...
    
    因此,输出将为:

    (*main.FormInfo)(0xc08200aa50)({
     Fields1: (string) (len=7) "value 1",
     Fields2: (string) (len=7) "value 2",
     Action: (string) (len=4) "save",
     PageTitle: (string) "",
     Id: (string) ""
    })
    
    编辑:

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <title>{{ .PageTitle }}</title>
        <meta http-equiv="Content-Type" content="text/html;" charset="utf-8">
        <meta charset="UTF-8">
        <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
        <link rel="apple-touch-icon" href="/mobile.png" />
        <meta name="viewport" 
              content="initial-scale=1.0,width=device-width,user-scalable=no">
        <meta name="generator" content="Go">
        <link rel="stylesheet" href="/base.css" type="text/css">
      </head>
    
      <body>
    
          <div class="mainbody">
            {{ yield }}
          </div>
    
      </body>
    
    </html>
    
    <h1>{{ .PageTitle }}</h1>
    
    <form action="/formtest/{{ .Id }}" method="POST">
    
        <div class="details">
          <label>Question 1</label>
          <input type="text" name="fields[0]" value="value 1" />
        </div>
    
        <div class="details">
          <label>Question 2</label>
          <input type="text" name="fields[1]" value="value 2" />
        </div>
    
        <div class="details">
          <input type="submit" name="action" value="save" />
        </div>
    
    </form>
    
    (*main.FormInfo)(0xc820066c30)({
     Fields: ([]string) <nil>,
     Action: (string) (len=4) "save",
     PageTitle: (string) "",
     Id: (string) ""
    })
    
    Fields: ([]string) <contains two values submitted>,
    
    如果您更改

    ...
    <input type="text" name="fields"...
    <input type="text" name="fields"...
    

    不更改其原始代码。

    提供MCVE。现在您的代码不正确。感谢您的反馈。我现在已经改正了。我会尽力回答的。为什么要在这个简单的示例中使用这么多库?如果要扫描数组,表单应该是什么样子?也就是说,我不想更改FormInfo的结构,我应该在模板中更改什么?