Мне нужно сделать еще одно представление, которое содержит эти 2 представления?
blockquote>Ответ: Нет
Нет ли другого способа такого как (без BigViewModel):
blockquote>Да, вы можете использовать Tuple (придает магии возможность иметь несколько моделей).
Код:
@model Tuple<LoginViewModel, RegisterViewModel> @using (Html.BeginForm("Login", "Auth", FormMethod.Post)) { @Html.TextBoxFor(tuple=> tuple.Item.Name) @Html.TextBoxFor(tuple=> tuple.Item.Email) @Html.PasswordFor(tuple=> tuple.Item.Password) } @using (Html.BeginForm("Login", "Auth", FormMethod.Post)) { @Html.TextBoxFor(tuple=> tuple.Item1.Email) @Html.PasswordFor(tuple=> tuple.Item1.Password) }
sql.NullInt64
существует, потому что SQL null
нельзя представить как Go int
. Это третье состояние, которое не может быть представлено ни одним значением int
.
Одним из решений этой проблемы было бы представление таких значений SQL как *int
, но для этого потребовалось бы выделение для случаев, когда значение не равно null
в базе данных, и выделения плохо влияют на производительность.
Разработчики пакета SQL придумали решение NullInt64
, которое кодирует третье состояние нуля в качестве дополнительного Valid
логического значения. Это не хорошее решение, но лучшее, что мы можем получить.
Я не уверен, возможно ли написать маршаллер JSON для NullInt64
, который бы работал так, как вы ожидаете.
По-прежнему существует проблема «третьего состояния» при сортировке в JSON. С ,omitempty
было бы также опущено 0
int, так как вы можете отличить 0 от «не существует» / null?
В любом случае они не написали собственный маршаллер для NullInt64
, поэтому он просто кодирует как структура, которая это есть.
Вы можете создать тип псевдонима для NullInt64
, написать маршаллер JSON для кодирования того, как вы хотите, в JSON (вам нужен псевдоним, потому что вы не можете добавлять методы к типам из других пакетов). Вам также нужно будет разыграть между NullInt64
и sql.NullInt64
.
Вы можете использовать пользовательский тип для null int64. Этот тип работает так, как вы ожидали.
Пример использования:
package main
import (
"encoding/json"
"database/sql/driver"
"fmt"
"strconv"
)
type user struct {
ID int `db:"id"`
Name string `db:"name"`
// pointer needed to omitempty work, otherwise output will be "age": null
Age *NullInt64 `db:"age" json:"age,omitempty"`
}
func main() {
u := user{ID: 1, Name: "John"}
j, _ := json.Marshal(u)
fmt.Printf("%s\n", j)
}
// Output:
// {"ID":1,"Name":"John"}
type NullInt64 struct {
Val int64
IsValid bool
}
func NewNullInt64(val interface{}) NullInt64 {
ni := NullInt64{}
ni.Set(val)
return ni
}
func (ni *NullInt64) Scan(value interface{}) error {
ni.Val, ni.IsValid = value.(int64)
return nil
}
func (ni NullInt64) Value() (driver.Value, error) {
if !ni.IsValid {
return nil, nil
}
return ni.Val, nil
}
func (ni *NullInt64) Set(val interface{}) {
ni.Val, ni.IsValid = val.(int64)
}
func (ni NullInt64) MarshalJSON() ([]byte, error) {
if !ni.IsValid {
return []byte(`null`), nil
}
return []byte(strconv.FormatInt(ni.Val, 10)), nil
}
func (ni *NullInt64) UnmarshalJSON(data []byte) error {
if data == nil || string(data) == `null` {
ni.IsValid = false
return nil
}
val, err := strconv.ParseInt(string(data), 10, 64)
if err != nil {
ni.IsValid = false
return err
}
ni.Val = val
ni.IsValid = true
return nil
}
func (ni NullInt64) String() string {
if !ni.IsValid {
return `<nil>`
}
return strconv.FormatInt(ni.Val, 10)
}