Slices和Maps的边界拷贝操作

切片和 map 包含一个指针来指向底层数据,所以当需要复制他们时需要特别注意。

接收Slices和Maps

请记住,如果存储了对 slice 或 map 的引用,那么用户是可以对其进行修改。

BadGood
  1. func (d Driver) SetTrips(trips []Trip) {
  2. d.trips = trips
  3. }
  4. trips :=
  5. d1.SetTrips(trips)
  6. // 是想修改 d1.trips 吗?
  7. trips[0] =
  1. func (d Driver) SetTrips(trips []Trip) {
  2. d.trips = make([]Trip, len(trips))
  3. copy(d.trips, trips)
  4. }
  5. trips :=
  6. d1.SetTrips(trips)
  7. // 修改 trips[0] 并且不影响 d1.trips 。
  8. trips[0] =

返回 Slices 和 Maps

同理,谨慎提防用户修改暴露内部状态的 slices 和 maps 。

BadGood
  1. type Stats struct {
  2. sync.Mutex
  3. counters map[string]int
  4. }
  5. // Snapshot 返回当前状态
  6. func (s Stats) Snapshot() map[string]int {
  7. s.Lock()
  8. defer s.Unlock()
  9. return s.counters
  10. }
  11. // snapshot 不再受锁保护了!
  12. snapshot := stats.Snapshot()
  1. type Stats struct {
  2. sync.Mutex
  3. counters map[string]int
  4. }
  5. func (s Stats) Snapshot() map[string]int {
  6. s.Lock()
  7. defer s.Unlock()
  8. result := make(map[string]int, len(s.counters))
  9. for k, v := range s.counters {
  10. result[k] = v
  11. }
  12. return result
  13. }
  14. // snapshot 是一分拷贝的内容了
  15. snapshot := stats.Snapshot()