Mastering Dependency Injection in Go with Google Wire
This article introduces Google Wire, a static‑analysis‑based dependency injection tool for Go, covering its key features, installation steps, core usage patterns—including defining dependencies, creating providers, generating code, and best practices such as modular management, interface abstraction, and testing with mock implementations.
Dependency Injection (DI) is a design pattern that moves dependency creation outside of a class to improve testability, maintainability, and flexibility. In Go, github.com/google/wire is a powerful, efficient DI tool that uses static code analysis to generate initialization code.
1. Introduction to Google Wire
Google Wire is an open‑source DI generator for Go. It reads annotations and performs static analysis to automatically generate dependency‑initialization code, simplifying manual dependency management.
Key Features
Static analysis : generates code at compile time, avoiding runtime overhead.
Simplified dependency management : automatically creates initialization code, reducing errors and complexity.
Easy integration : works with existing Go projects without major code changes.
2. Installing Google Wire
Install Wire using Go's package tool: go get -u github.com/google/wire/cmd/wire Verify the installation: wire help If the help output appears, the installation succeeded.
3. Basic Usage
1. Define dependencies
Example with a simple application that needs a database connection and an HTTP server:
package main
import (
"fmt"
"net/http"
)
// Database defines a DB struct
type Database struct {
DSN string
}
// NewDatabase creates a new Database instance
func NewDatabase(dsn string) *Database {
return &Database{DSN: dsn}
}
// Server defines an HTTP server struct
type Server struct {
DB *Database
}
// NewServer creates a new Server instance
func NewServer(db *Database) *Server {
return &Server{DB: db}
}2. Create Provider
Providers describe how to construct dependencies. In wire.go:
// +build wireinject
package main
import "github.com/google/wire"
// InitializeServer declares that Server depends on Database and uses NewDatabase and NewServer to build them.
func InitializeServer(dsn string) *Server {
wire.Build(NewDatabase, NewServer)
return &Server{}
}3. Generate code
Run the Wire command to generate the concrete initialization code: wire The generated wire_gen.go looks like:
// Code generated by Wire. DO NOT EDIT.
package main
import "github.com/google/wire"
func InitializeServer(dsn string) *Server {
database := NewDatabase(dsn)
server := NewServer(database)
return server
}4. Use generated code
In main.go:
package main
import "fmt"
func main() {
dsn := "user:password@/dbname"
server := InitializeServer(dsn)
fmt.Println("Server initialized with database:", server.DB.DSN)
}4. Best Practices
1. Modular dependency management
Separate dependencies per module, e.g., a dedicated file for database providers:
// database.go
package main
import "github.com/google/wire"
var DatabaseSet = wire.NewSet(NewDatabase)2. Use interfaces
Define dependencies as interfaces to increase flexibility:
// database.go
package main
type Database interface {
Connect() error
}
type MySQLDatabase struct {
DSN string
}
func (db *MySQLDatabase) Connect() error { return nil }
func NewMySQLDatabase(dsn string) *MySQLDatabase {
return &MySQLDatabase{DSN: dsn}
}
// wire.go
package main
import "github.com/google/wire"
var DatabaseSet = wire.NewSet(NewMySQLDatabase, wire.Bind(new(Database), new(*MySQLDatabase)))3. Testing
Dependency injection makes unit testing straightforward by injecting mock implementations:
// server_test.go
package main
import (
"testing"
"github.com/stretchr/testify/assert"
)
type MockDatabase struct{}
func (db *MockDatabase) Connect() error { return nil }
func TestServer(t *testing.T) {
db := &MockDatabase{}
server := NewServer(db)
assert.NotNil(t, server)
}5. Conclusion
Google Wire provides fast, static‑analysis‑based code generation for dependency injection, reducing manual wiring, improving modularity, and simplifying testing in Go projects.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Ops Development & AI Practice
DevSecOps engineer sharing experiences and insights on AI, Web3, and Claude code development. Aims to help solve technical challenges, improve development efficiency, and grow through community interaction. Feel free to comment and discuss.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
