Locks Passed By Value

ID

go.locks_passed_by_value

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

Go

Tags

concurrency, reliability

Description

Reports a function parameter whose type is a sync.Mutex or sync.RWMutex passed by value rather than by pointer.

Rationale

A sync lock must not be copied after first use: copying duplicates the lock’s internal state, so the copy is an independent lock. A function that takes a mutex by value receives a copy, so locking it protects nothing the caller can observe and both sides can believe they hold the lock — a silent data race. Passing a pointer shares the one lock.

// Bad
func f(mu sync.Mutex)  { mu.Lock() }  // FLAW — operates on a copy of the lock

// Good
func g(mu *sync.Mutex) { mu.Lock() }  // OK — shares the caller's lock

Remediation

Pass the lock by pointer (*sync.Mutex / *sync.RWMutex), or embed it in a struct and pass that struct by pointer.