3 回答
TA贡献2037条经验 获得超6个赞
有没有更简单的方法可以像 PHP 那样将我的表单数组作为 Golang 中的实际地图?
您可以使用PostForm该http.Request类型的成员。它是一种类型url.Values——实际上是 (ta-da) a map[string][]string,你可以这样对待它。不过,您仍然需要先打电话req.ParseForm()。
if err := req.ParseForm(); err != nil {
// handle error
}
for key, values := range req.PostForm {
// [...]
}
请注意,这PostForm是字符串列表的映射。这是因为理论上,每个字段都可以在 POST 正文中出现多次。该PostFormValue()方法通过隐式返回多个值中的第一个来处理此问题(意思是,当您的 POST 正文为 时&foo=bar&foo=baz,req.PostFormValue("foo")则将始终返回"bar")。
另请注意,PostForm永远不会像您在 PHP 中使用的那样包含嵌套结构。由于 Go 是静态类型的,POST 表单值将始终是string(name) 到[]string(value/s)的映射。
就个人而言,我不会contact[email]在 Go 应用程序中对 POST 字段名称使用括号语法 ( );这是一个 PHP 特定的构造,无论如何,正如您已经注意到的,Go 并没有很好地支持它。
我是应该一个一个地检索数据(很乏味,我可能会在某个时候更改表单数据并重新编译...)还是像我在第二个示例中所做的那样迭代整个过程。
可能没有正确的答案。如果您将 POST 字段映射到具有静态字段的结构,则必须在某个时候显式映射它们(或用于reflect实现一些神奇的自动映射)。
TA贡献1852条经验 获得超1个赞
我有一个类似的问题,所以我写了这个函数
func ParseFormCollection(r *http.Request, typeName string) []map[string]string {
var result []map[string]string
r.ParseForm()
for key, values := range r.Form {
re := regexp.MustCompile(typeName + "\\[([0-9]+)\\]\\[([a-zA-Z]+)\\]")
matches := re.FindStringSubmatch(key)
if len(matches) >= 3 {
index, _ := strconv.Atoi(matches[1])
for ; index >= len(result); {
result = append(result, map[string]string{})
}
result[index][matches[2]] = values[0]
}
}
return result
}
它将表单键值对的集合转换为字符串映射列表。例如,如果我有这样的表单数据:
Contacts[0][Name] = Alice
Contacts[0][City] = Seattle
Contacts[1][Name] = Bob
Contacts[1][City] = Boston
我可以调用我的函数传递“联系人”的类型名称:
for _, contact := range ParseFormCollection(r, "Contacts") {
// ...
}
它将返回一个包含两个地图对象的列表,每个地图都包含“名称”和“城市”的键。在 JSON 表示法中,它看起来像这样:
[
{
"Name": "Alice",
"City": "Seattle"
},
{
"Name": "Bob",
"City": "Boston"
}
]
顺便说一句,这正是我在 ajax 请求中将数据发布到服务器的方式:
$.ajax({
method: "PUT",
url: "/api/example/",
dataType: "json",
data: {
Contacts: [
{
"Name": "Alice",
"City": "Seattle"
},
{
"Name": "Bob",
"City": "Boston"
}
]
}
})
如果您的表单数据键结构与我的不太匹配,那么您可能会调整我正在使用的正则表达式以满足您的需求。
TA贡献1891条经验 获得超3个赞
我有同样的问题。在我来自的 Ruby/Rails 世界中,数组表单参数的提交也是惯用的。但是,经过一些研究,看起来这并不是真正的“Go-way”。
我一直在使用点前缀约定:contact.name,contact.email,等。
func parseFormHandler(writer http.ResponseWriter, request *http.Request) {
request.ParseForm()
userParams := make(map[string]string)
for key, _ := range request.Form {
if strings.HasPrefix(key, "contact.") {
userParams[string(key[8:])] = request.Form.Get(key)
}
}
fmt.Fprintf(writer, "%#v\n", userParams)
}
func main() {
server := http.Server{Addr: ":8088"}
http.HandleFunc("/", parseFormHandler)
server.ListenAndServe()
}
运行此服务器,然后将其卷曲:
$ curl -id "contact.name=Jeffrey%20Lebowski&contact.email=thedude@example.com&contact.message=I%20hate%20the%20Eagles,%20man." http://localhost:8088
结果是:
HTTP/1.1 200 OK
Date: Thu, 12 May 2016 16:41:44 GMT
Content-Length: 113
Content-Type: text/plain; charset=utf-8
map[string]string{"name":"Jeffrey Lebowski", "email":"thedude@example.com", "message":"I hate the Eagles, man."}
使用大猩猩工具包
您还可以使用Gorilla Toolkit 的 Schema Package将表单参数解析为结构体,如下所示:
type Submission struct {
Contact Contact
}
type Contact struct {
Name string
Email string
Message string
}
func parseFormHandler(writer http.ResponseWriter, request *http.Request) {
request.ParseForm()
decoder := schema.NewDecoder()
submission := new(Submission)
err := decoder.Decode(submission, request.Form)
if err != nil {
log.Fatal(err)
}
fmt.Fprintf(writer, "%#v\n", submission)
}
运行此服务器,然后将其卷曲:
$ curl -id "Contact.Name=Jeffrey%20Lebowski&Contact.Email=thedude@example.com&Contact.Message=I%20hate%20the%20Eagles,%20man." http://localhost:8088
结果是:
HTTP/1.1 200 OK
Date: Thu, 12 May 2016 17:03:38 GMT
Content-Length: 128
Content-Type: text/plain; charset=utf-8
&main.Submission{Contact:main.Contact{Name:"Jeffrey Lebowski", Email:"thedude@example.com",
- 3 回答
- 0 关注
- 187 浏览
添加回答
举报