Réception de tranches et de cartes
N'oubliez pas que lorsqu'une carte ou une tranche est passée en tant que paramètre de fonction, si vous stockez une référence à ces derniers, les utilisateurs peuvent les modifier.
Approche non recommandée :
func (d *Driver) SetTrips(trips []Trip) {
d.trips = trips
}
trips := ...
d1.SetTrips(trips)
// Essayez-vous de modifier d1.trips ?
trips[0] = ...
Approche recommandée :
func (d *Driver) SetTrips(trips []Trip) {
d.trips = make([]Trip, len(trips))
copy(d.trips, trips)
}
trips := ...
d1.SetTrips(trips)
// Ici, nous modifions trips[0], mais cela n'affectera pas d1.trips
trips[0] = ...
Retour de tranches ou de cartes
De même, faites attention aux utilisateurs qui modifient une carte ou une tranche qui expose un état interne.
Approche non recommandée :
type Stats struct {
mu sync.Mutex
counters map[string]int
}
// Snapshot retourne l'état actuel
func (s *Stats) Snapshot() map[string]int {
s.mu.Lock()
defer s.mu.Unlock()
return s.counters
}
// snapshot n'est plus protégé par le mutex
// donc tout accès à snapshot sera soumis à une course de données et affectera stats.counters
snapshot := stats.Snapshot()
Approche recommandée :
type Stats struct {
mu sync.Mutex
counters map[string]int
}
func (s *Stats) Snapshot() map[string]int {
s.mu.Lock()
defer s.mu.Unlock()
result := make(map[string]int, len(s.counters))
for k, v := range s.counters {
result[k] = v
}
return result
}
// snapshot est maintenant une copie
snapshot := stats.Snapshot()