dongzongzi0379 2013-11-04 17:45
浏览 47
已采纳

重定向后Golang大猩猩会话保留表单数据

From logic point of view I am trying to preserve partial form data between redirects for better user experience so user won't have to fill entire form again, just the part that was invalid.

From programing point of view I am trying to save request.PostForm data structure in gorilla session's flashes. The only thing I manage to retrieve after redirect is string representation of memory address like this [0xc2001c8b10].

Here is the part where I save flashes data after validation error (request.ParseForm() was executed before this):

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

Also I tried registering structure with gob without effect:

func init() {
    gob.Register(&url.Values{})
}

Form values are in lower case, eg. "first_name", "last_name" if that could have any influence on this behavior.

Please keep in mind that I successfully manage to retrieve "messages" after redirect, only problem I have is with structural data.

Am I doing something wrong or is there maybe another approach to fill partial forms after redirect that I am not aware of?

  • 写回答

1条回答 默认 最新

  • dongsi3826 2013-11-04 18:21
    关注

    Your problem is that you're working with values of type interface{}, which is the generic type and used when there can be more than one type. This is the case for gorilla's session.Flashes() method as it can return arbitrary user data (whatever you put in).

    You can reproduce what you're experiencing with this code (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())
    }
    

    When running this program you will see output like this:

    Some data: [0xc010000000]

    This is the same you're experiencing. The reason for this is that fmt.Println does not step through all levels of abstraction of pointers and interfaces and stops at a certain level unless you tell it to print everything. So if you use

    fmt.Printf("Some data: %#v
    ", Flashes())
    

    you will indeed see your data:

    Some data: []interface {}{(*main.MyData)(0xc010000000)}

    What you have to do to access the data is to match the resulted data for the type you're expecting. You have to do a 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")
        }
    }
    

    In the example above the first flash returned by Flashes() is used and asserted to be of type *MyData. If it is indeed this type, then it's value is printed to the console. Otherwise an error message (albeit not a good one) is printed to the console. After asserting a variable of being some type, the asserted value is of the asserted type. That is the v in the example above is of type *MyType.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥100 c语言,请帮蒟蒻写一个题的范例作参考
  • ¥15 名为“Product”的列已属于此 DataTable
  • ¥15 安卓adb backup备份应用数据失败
  • ¥15 eclipse运行项目时遇到的问题
  • ¥15 关于#c##的问题:最近需要用CAT工具Trados进行一些开发
  • ¥15 南大pa1 小游戏没有界面,并且报了如下错误,尝试过换显卡驱动,但是好像不行
  • ¥15 没有证书,nginx怎么反向代理到只能接受https的公网网站
  • ¥50 成都蓉城足球俱乐部小程序抢票
  • ¥15 yolov7训练自己的数据集
  • ¥15 esp8266与51单片机连接问题(标签-单片机|关键词-串口)(相关搜索:51单片机|单片机|测试代码)