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()