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