Skip to content
Reliability and safety

syncmapatomicity

Checks non-atomic sync.Map load-and-delete claims.

Fix offeredNo

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
}