我是一名PHP开发人员,但目前正在迁移到Golang...我正在try 从表单(Post方法)检索数据:

<!-- A really SIMPLE form -->
<form class="" action="/Contact" method="post">
  <input type="text" name="Contact[Name]" value="Something">   
  <input type="text" name="Contact[Email]" value="Else">
  <textarea name="Contact[Message]">For this message</textarea>
  <button type="submit">Submit</button>
</form>

在PHP中,我将简单地使用以下代码来获取数据:

<?php 
   print_r($_POST["Contact"])
?>
// Output would be something like this:
Array
(
    [Name] => Something
    [Email] => Else
    [Message] => For this message
)

但在围棋中...我可以一个接一个地获取,也可以获取全部内容,但不能只获取Contact[]数组,比如PHP

我想到了两种解决方案:

1)逐一获取:

// r := *http.Request
err := r.ParseForm()

if err != nil {
    w.Write([]byte(err.Error()))
    return
}

contact := make(map[string]string)

contact["Name"] = r.PostFormValue("Contact[Name]")
contact["Email"] = r.PostFormValue("Contact[Email]")
contact["Message"] = r.PostFormValue("Contact[Message]")

fmt.Println(contact)

// Output
map[Name:Something Email:Else Message:For this Message]

请注意,映射键是完整的:"Contact[Name]".

2)范围全图r.Form并"解析|获得"那些带有前缀的值 "Contact[",然后将"Contact["和"]"替换为空字符串 因此,只有这样的PHP示例才能获得表单数组键

我自己go 做这项工作,但是...在整个表单上进行扫描可能不是一个好主意(?)

// ContactPost process the form sent by the user
func ContactPost(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
    err := r.ParseForm()

    if err != nil {
        w.Write([]byte(err.Error()))
        return
    }

    contact := make(map[string]string)

   for i := range r.Form {
       if strings.HasPrefix(i, "Contact[") {
           rp := strings.NewReplacer("Contact[", "", "]", "")
           contact[rp.Replace(i)] = r.Form.Get(i)
       }
   }

    w.Write([]byte(fmt.Sprint(contact)))
}
//Output
map[Name:Something Email:Else Message:For this Message]

这两种解决方案给我的输出都是一样的.但在第二个示例中,我不一定需要知道"Contact[]"的键

我知道...我可能只是忘记了"表单数组",在我的输入上使用name="Email",然后一个接一个地检索,但是...我已经介绍了一些场景,其中我使用一个包含两个以上数据数组的表单,并对每个表单执行不同的操作,比如ORMs

Question 1:有没有像PHP一样,用Golang将我的表单数组作为实际映射的更简单的方法?

Question 2:我应该逐个检索数据吗(尽可能繁琐,我可能会在某个时候更改表单数据并重新编译……)或者像我在第二个示例中所做的那样迭代整个过程.

抱歉我的英语不好...提前谢谢!

推荐答案

有没有一种更简单的方法可以像PHP那样,在Golang中获得我的表单数组作为实际的映射?

您可以使用http.Request类型的PostForm成员.它是url.Values型的,实际上是(ta da)a map[string][]string,你可以这样对待它.不过,你还是需要先打req.ParseForm().

if err := req.ParseForm(); err != nil {
    // handle error
}

for key, values := range req.PostForm {
    // [...]
}

Note that 100 is a map of lists of strings.这是因为从理论上讲,每个字段可以在帖子正文中多次出现.PostFormValue()方法通过隐式返回多个值的first来处理这个问题(这意味着,当您的POST正文为&foo=bar&foo=baz时,req.PostFormValue("foo")将始终返回"bar").

Also note that 100 will never contain nested structures就像你是从PHP中使用的一样.由于Go是静态类型的,POST form值always将是string(名称)到[]string(值/s)的映射.

就我个人而言,我不会在Go应用程序中使用括号语法(contact[email])作为POST字段名;这是一个特定于PHP的构造,正如您已经注意到的,Go不太支持它.

我应该一个接一个地检索数据吗(尽可能繁琐,我可能会在某个时候更改表单数据并重新编译……)或者像我在第二个示例中所做的那样迭代整个过程.

对此可能没有正确的答案.如果要将POST字段映射到带有静态字段的 struct ,则必须在某个点显式映射它们(或者使用reflect实现一些神奇的自动映射).

Go相关问答推荐

GORM Find方法中缺少字段

如何在Golang中获取mp3文件的持续时间?

在Uber FX中实现后台进程正常关闭的正确方式是什么?

日志(log)文件不在 golang 的日志(log)目录中

Docker 执行失败并显示cmd/ENTRYPOINT 中的命令未找到

在golang中以JSON格式获取xwwwformurlencoded请求的嵌套键值对

如何在 Go 中将 int 转换为包含 complex128 的泛型类型?

如何在 Go 服务中导入 monorepo 中的包?

加载 docker 镜像失败

致命错误 - 所有 Goroutines 都睡着了!僵局

使用自定义处理程序 nats golang 保留订阅方法

如何在切片增长时自动将切片的新元素添加到函数参数

如何使用 go-playground/validator 编写 snake case 绑定标签?

如何在自定义验证函数中获取 struct 名称

在 Go GRPC 服务器流式拦截器上修改元数据

处理程序后访问 HTTP 请求上下文

Go AST:获取所有 struct

GRPC 反向代理混淆 GRPC 和 GRPC-Web

在 Go 中将十六进制转换为带符号的 Int

Golang API 的 HTTPS