دریافت برش‌ها و نقشه‌ها

به خاطر داشته باشید که هنگامی که یک نقشه یا یک برش به عنوان پارامتر یک تابع ارسال می‌شود، اگر شما یک مرجع به آن‌ها ذخیره کنید، کاربران می‌توانند آن‌ها را اصلاح کنند.

روش توصیه نشده:

func (d *Driver) SetTrips(trips []Trip) {
  d.trips = trips
}

trips := ...
d1.SetTrips(trips)

// آیا شما سعی دارید تا d1.trips را اصلاح کنید؟
trips[0] = ...

روش توصیه شده:

func (d *Driver) SetTrips(trips []Trip) {
  d.trips = make([]Trip, len(trips))
  copy(d.trips, trips)
}

trips := ...
d1.SetTrips(trips)

// در این‌جا ما trips[0] را اصلاح می‌کنیم، اما این تاثیری بر d1.trips نخواهد داشت
trips[0] = ...

بازگرداندن برش‌ها یا نقشه‌ها

به همان‌شکل، به موضع داشته باشید کاربران یک نقشه یا برش را که وضعیت داخلی را آشکار می‌کند، اصلاح کنند.

روش توصیه نشده:

type Stats struct {
  mu sync.Mutex
  counters map[string]int
}

// Snapshot وضعیت فعلی را بازمی‌گرداند
func (s *Stats) Snapshot() map[string]int {
  s.mu.Lock()
  defer s.mu.Unlock()

  return s.counters
}

// snapshot دیگر توسط mutex محافظت نمی‌شود
// بنابراین هر دسترسی به snapshot مشمول گردش داده خواهد بود و تاثیری بر روی stats.counters خواهد داشت
snapshot := stats.Snapshot()

روش توصیه شده:

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 یک نسخه است
snapshot := stats.Snapshot()