Reliability and safety
syncmapatomicity
Checks non-atomic sync.Map load-and-delete claims.
What it detects
A separate Load followed by Delete allows another goroutine to observe or
claim the same entry between operations. Use LoadAndDelete when the loaded
value is consumed as the successfully removed entry.
Checks
| Check | What it detects |
|---|---|
non-atomic-claim |
Reports separate sync.Map Load and Delete operations used to claim one value. |
Why this is flagged
Another goroutine can change the map between two separate operations. The caller may then process a value it did not actually remove, allowing the same work to be claimed twice or a newer value to be deleted accidentally.
Further reading: sync.Map.LoadAndDelete.
How to fix it
Replace the separate Load and Delete with one LoadAndDelete operation.
Only process the returned value when that atomic operation reports that the
entry was present.
Examples
Flagged code
func take(cache *sync.Map, key string) any { value, ok := cache.Load(key) if ok { // gohawk: sync.Map Load and Delete do not atomically claim the value cache.Delete(key) return value } return nil}Accepted code
func takeAtomically(cache *sync.Map, key string) any { value, deleted := cache.LoadAndDelete(key) if deleted { return value } return nil}