Avoid global state in Go
Global state in Go can feel like a shortcut—but it’s one that leads straight into long-term complexity. Whether you're writing a web service, CLI tool, or package, using global variables makes your code harder to test, maintain, and reason about. The good news? Go's simplicity makes it easy to avoid. Use structs and dependency injection instead.
Why Global State Is a Problem
Global variables introduce hidden dependencies—any part of your code can change them at any time. This leads to:
- Tight coupling: Code becomes dependent on global configuration.
- Race conditions: Concurrent access to shared globals causes subtle bugs.
- Poor testability: Tests must reset or mock globals, which is brittle and messy.
How It Complicates Testing
Suppose you have a global logger or database connection:
var db *sql.DB
func GetUser(id int) (*User, error) {
return db.QueryRow("SELECT * FROM users WHERE id = ?", id)
}
Now imagine writing a unit test for GetUser
. You have to:
- Ensure
db
is initialized. - Possibly mock it—globally.
- Avoid breaking other tests that also use
db
.
This creates test coupling, where tests depend on each other’s state. One test failing to reset the global properly can cause unrelated tests to fail.
A Better Pattern: Structs + Dependency Injection
Encapsulate dependencies in a struct and pass them in:
type Service struct {
DB *sql.DB
}
func (s *Service) GetUser(id int) (*User, error) {
return s.DB.QueryRow("SELECT * FROM users WHERE id = ?", id)
}
And then wire it up in main
:
func main() {
db := setupDB()
service := &Service{DB: db}
// Use service.GetUser(...)
}
In tests:
func TestGetUser(t *testing.T) {
mockDB := setupMockDB()
service := &Service{DB: mockDB}
// assert service.GetUser(...)
}
Final Thought
Avoiding global state isn’t about purity—it’s about clarity, testability, and safety. Go gives you everything you need to do this well. Use structs to group your dependencies, inject them explicitly, and you’ll write code that’s easier to test, understand, and grow.
Leave global state behind. Your future self (and your test suite) will thank you.