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
}