In Go non puoi definire valori predefiniti per i campi, saranno sempre il valore zero del loro tipo quando viene creato un nuovo valore struct (a meno che tu non usi un valore letterale composto in cui puoi dare un valore diverso in modo esplicito).
Quindi un'opzione sarebbe quella di creare una funzione simile a un costruttore NewUser()
che imposterebbe questo campo e utilizzerà sempre questa funzione per creare nuovi utenti:
func NewUser() *User {
return &User{
CreatedAt: time.Now(),
}
}
Ovviamente questo non può essere forzato, e anche questo conterrà il timestamp dell'User
struct creazione di valore e non quando viene salvato.
Un altro approccio migliore consiste nell'utilizzare una logica di marshalling personalizzata.
Puoi scrivere una logica di marshalling personalizzata implementando bson.Getter
. GetBSON()
è responsabile di fornire un valore che verrà effettivamente salvato. Vogliamo lo stesso User
istanza da salvare, solo il suo CreatedAt
campo impostato prima:
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
}
Nota che un nuovo my
il tipo viene creato e restituito. Il motivo è evitare l'overflow dello stack. Semplicemente restituendo un valore di tipo *User
è negativo, perché implementa bson.Getter
, quindi GetBSON()
verrebbe chiamato all'infinito. Il nuovo my
type non ha questo metodo, quindi non si verifica una "ricorsività" infinita (il type
la parola chiave crea un nuovo tipo e non "eredita" i metodi del tipo sottostante).
Nota che questa soluzione sovrascriverà (ripristinerà) anche il CreatedAt
campo) anche se desideri salvare nuovamente un User
. Quindi dovremmo aggiungere un controllo se il CreatedAt
il campo è compilato e impostarlo solo se è il valore zero:
func (u *User) GetBSON() (interface{}, error) {
if u.CreatedAt.IsZero() {
u.CreatedAt = time.Now()
}
type my *User
return my(u), nil
}
Vedi anche domanda correlata/simile:accesso a MongoDB da Go