- Slices和Maps的边界拷贝操作
- 接收Slices和Maps
- 返回 Slices 和 Maps
Slices和Maps的边界拷贝操作
切片和 map 包含一个指针来指向底层数据,所以当需要复制他们时需要特别注意。
接收Slices和Maps
请记住,如果存储了对 slice 或 map 的引用,那么用户是可以对其进行修改。
Bad | Good |
---|
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] = …
|
返回 Slices 和 Maps
同理,谨慎提防用户修改暴露内部状态的 slices 和 maps 。
Bad | Good |
---|
type Stats struct { sync.Mutex
counters map[string]int }
// Snapshot 返回当前状态 func (s Stats) Snapshot() map[string]int { s.Lock() defer s.Unlock()
return s.counters }
// snapshot 不再受锁保护了! snapshot := stats.Snapshot()
|
type Stats struct { sync.Mutex
counters map[string]int }
func (s Stats) Snapshot() map[string]int { s.Lock() defer s.Unlock()
result := make(map[string]int, len(s.counters)) for k, v := range s.counters { result[k] = v } return result }
// snapshot 是一分拷贝的内容了 snapshot := stats.Snapshot()
|