How to Separate Business Logic from Infrastructure in Go

Separate business logic from infrastructure in Go by defining interfaces for dependencies and injecting concrete implementations at runtime.

Separate business logic from infrastructure in Go by defining interfaces for external dependencies and injecting concrete implementations via dependency injection. This ensures your core logic depends only on abstractions, not specific tools like databases or HTTP clients.

// Define an interface for the infrastructure dependency
type UserRepository interface {
    GetByID(id string) (*User, error)
}

// Business logic depends only on the interface
type UserService struct {
    repo UserRepository
}

func NewUserService(repo UserRepository) *UserService {
    return &UserService{repo: repo}
}

// Infrastructure implementation satisfies the interface
type PostgresUserRepo struct {
    db *sql.DB
}

func (r *PostgresUserRepo) GetByID(id string) (*User, error) {
    // Database logic here
    return nil, nil
}

// Wire them together in main()
func main() {
    repo := &PostgresUserRepo{db: openDB()}
    service := NewUserService(repo)
    // Use service
}