В Go не можете да дефинирате стойности по подразбиране за полета, те винаги ще бъдат нулевата стойност на техния тип, когато се създаде нова стойност на структура (освен ако не използвате съставен литерал, където можете да дадете различна стойност изрично).
Така че една от опциите би била да създадете подобна на конструктор функция NewUser()
което ще зададе това поле и винаги използва тази функция за създаване на нови потребители:
func NewUser() *User {
return &User{
CreatedAt: time.Now(),
}
}
Разбира се, това не може да бъде принудено, а също така ще задържи времевата марка на User
struct създаване на стойност, а не когато е запазена.
Друг, по-добър подход е да използвате персонализирана логика за маршалиране.
Можете да напишете персонализирана логика за маршалиране, като внедрите bson.Getter
. GetBSON()
е отговорен да предостави стойност, която действително ще бъде запазена. Искаме същия User
екземпляр, който трябва да бъде запазен, само неговият CreatedAt
поле, зададено преди:
type User struct {
CreatedAt time.Time `json:"created_at" bson:"created_at"`
}
func (u *User) GetBSON() (interface{}, error) {
u.CreatedAt = time.Now()
type my *User
return my(u), nil
}
Имайте предвид, че нов my
типът се създава и връща. Причината за това е да се избегне препълването на стека. Просто връщане на стойност от тип *User
е лошо, защото имплементира bson.Getter
, така че GetBSON()
ще ви се обаждат безкрайно. Новият my
type няма този метод, така че безкрайната "рекурсия" не се случва (type
ключова дума създава нов тип и не "наследява" методи на основния тип).
Имайте предвид, че това решение също ще презапише (пренастрои) CreatedAt
поле), дори ако просто искате да запишете отново User
. Така че трябва да добавим проверка дали CreatedAt
полето е попълнено и го задайте само ако е нулевата стойност:
func (u *User) GetBSON() (interface{}, error) {
if u.CreatedAt.IsZero() {
u.CreatedAt = time.Now()
}
type my *User
return my(u), nil
}
Вижте също свързан / подобен въпрос:Достъп до MongoDB от Go