Skip to content
Reliability and safety

globalstate

Checks mutable package-level state.

AvailabilityOpt-in
Fix offeredNo

What it detects

Reports mutable package-level variables such as maps, slices, pointers, interfaces, channels, and function values. Known immutable patterns and explicitly configured names or types are excluded.

Checks

Check What it detects
mutable-package-state*
Reports mutable package-level state without an explicit owner.

* Opt-in; requires explicit selection.

Why this is flagged

Mutable package state creates hidden dependencies between callers and tests. It is also easy for goroutines to access it without synchronization, leading to data races and behavior that depends on execution order.

How to fix it

Put the state on a type with a clear owner and pass that value to the code that needs it. If the state must be shared concurrently, keep its synchronization beside it and expose safe operations instead of the raw value.

Examples

Flagged code

type User struct {
Name string
}
// gohawk: mutable package state users requires an immutable owner or //gohawk:ignore globalstate
var users = map[string]User{}
func rememberUser(id string, user User) {
users[id] = user
}

Accepted code

type StoredUser struct {
Name string
}
type Store struct {
users map[string]StoredUser
}
func NewStore() *Store {
return &Store{users: make(map[string]StoredUser)}
}
func (store *Store) Remember(id string, user StoredUser) {
store.users[id] = user
}

Options

Knob Default Effect
allow-names empty Comma-separated package variable names to allow.
allow-types empty Comma-separated fully-qualified named types to allow.

Type allowlists use the full import path:

Terminal window
gohawk -enable=globalstate \
-globalstate.allow-names=metrics,registry \
-globalstate.allow-types=example.com/project.Registry \
./...