Сессии горилл Голанга, сохраняющие данные формы после перенаправления

С логической точки зрения я пытаюсь сохранить частичные данные формы между перенаправлениями для лучшего взаимодействия с пользователем, чтобы пользователю не пришлось снова заполнять всю форму, только ту часть, которая была недействительной.

С точки зрения программирования, я пытаюсь сохранить структуру данных 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", если это может повлиять на это поведение.

Пожалуйста, имейте в виду, что мне удалось получить "сообщения" после перенаправления, единственная проблема, с которой я столкнулся, - это структурные данные.

Я делаю что-то не так или, может быть, есть другой подход для заполнения частичных форм после перенаправления, о котором я не знаю?

1 ответ

Решение

Ваша проблема в том, что вы работаете со значениями типа interface{}, который является универсальным типом и используется, когда может быть более одного типа. Это дело горилл session.Flashes()метод, поскольку он может возвращать произвольные пользовательские данные (все, что вы положили в).

Вы можете воспроизвести то, что вы испытываете с этим кодом ( в игре):

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)}

Чтобы получить доступ к данным, необходимо сопоставить полученные данные с ожидаемым типом. Вы должны сделать утверждение типа ( пример в игре):

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,

Другие вопросы по тегам