Reliability and safety
globalstate
Checks mutable package-level state.
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 globalstatevar 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:
gohawk -enable=globalstate \ -globalstate.allow-names=metrics,registry \ -globalstate.allow-types=example.com/project.Registry \ ./...