从逻辑的角度来看,我试图在重定向之间保留部分表单数据以获得更好的用户体验,因此用户不必再次填写整个表单,只需填写无效的部分。
从编程的角度来看,我试图在gorilla会话的闪存中保存request.PostForm数据结构。重定向后我唯一能够检索的就是内存地址的字符串表示,如[0xc2001c8b10]。
这是我在验证错误之后保存闪烁数据的部分(在此之前执行了request.ParseForm()):
session, _ := store.Get(request, "test")
session.AddFlash(err.Error(), "messages")
session.AddFlash(request.PostForm, "form_data")
session.Save(request, response)
http.Redirect(response, request, "/", http.StatusFound)
return
此外,我尝试使用gob注册结构而没有效果:
func init() {
gob.Register(&url.Values{})
}
表单值为小写,例如。 “first_name”,“last_name”,如果这可能对此行为产生任何影响。
请记住,我成功设法在重定向后检索“消息”,只有问题是结构数据。
我做错了什么或是否有其他方法可以在重定向后填写部分表单我不知道?
答案 0 :(得分:2)
您的问题是您正在处理interface{}
类型的值,这是通用类型
并在可以有多种类型时使用。大猩猩的session.Flashes()
就属于这种情况
方法,因为它可以返回任意用户数据(无论你放入什么)。
您可以使用此代码(on play)重现您遇到的内容:
type MyData struct {
X int
}
// Simulate Flashes() from gorilla, which returns a slice of interface{} values.
func Flashes() []interface{} {
x := &MyData{2}
// Convert x to type interface{}
interfaceValue := interface{}(x)
// Put converted x into a slice of type []interface{}
return []interface{}{interfaceValue}
}
func main() {
// See that [0xSOMETHING] is printed
fmt.Println("Some data:", Flashes())
}
运行此程序时,您将看到如下输出:
一些数据:[0xc010000000]
这与您的体验相同。原因是fmt.Println
确实如此
不跨步指针和接口的所有级别的抽象,并停止
一定程度,除非你告诉它打印一切。所以,如果你使用
fmt.Printf("Some data: %#v\n", Flashes())
你确实会看到你的数据:
一些数据:[] interface {} {(* main.MyData)(0xc010000000)}
访问数据所需要做的是匹配类型的结果数据 你期待的。您必须执行type assertion(example on play):
func main() {
value := Flashes()[0]
v, ok := value.(*MyData)
if ok {
fmt.Println("Some data:", v)
} else {
fmt.Println("Oh no, there's something else stored than expected")
}
}
在上面的示例中,Flashes()
返回的第一个闪存被使用并声明为
类型为*MyData
。如果它确实是这种类型,那么它的值将被打印到控制台。
否则,将向控制台输出错误消息(尽管不是一个好消息)。
在声明某个类型的变量之后,断言的值是断言的
类型。这就是上面示例中的v
属于*MyType
类型。