How to Implement Clean Architecture in Go

Complete Example

Clean Architecture in Go is implemented by separating your code into distinct layers: Domain, Application, Infrastructure, and Interface, where dependencies point inward toward the core business logic. Start by defining your domain entities and interfaces in a `domain` package, then implement use ca

How to Implement Clean Architecture in Go: Complete Example

Clean Architecture in Go is implemented by separating your code into distinct layers: Domain, Application, Infrastructure, and Interface, where dependencies point inward toward the core business logic. Start by defining your domain entities and interfaces in a domain package, then implement use cases in an application package that depend only on those interfaces, and finally wire concrete implementations (like databases or HTTP handlers) in infrastructure and interface packages.

// 1. Domain: Define core entities and interfaces
// File: domain/user.go
package domain

type User struct {
	ID   string
	Name string
}

type UserRepository interface {
	GetByID(id string) (*User, error)
}
// 2. Application: Define use cases depending on domain interfaces
// File: application/user_service.go
package application

import "yourmodule/domain"

type UserService struct {
	repo domain.UserRepository
}

func (s *UserService) GetUser(id string) (*domain.User, error) {
	return s.repo.GetByID(id)
}
// 3. Infrastructure: Implement domain interfaces (e.g., SQL)
// File: infrastructure/postgres_repo.go
package infrastructure

import (
	"database/sql"
	"yourmodule/domain"
)

type PostgresUserRepo struct {
	db *sql.DB
}

func (r *PostgresUserRepo) GetByID(id string) (*domain.User, error) {
	// SQL logic here
	var u domain.User
	// err := r.db.QueryRow("SELECT id, name FROM users WHERE id = ?", id).Scan(&u.ID, &u.Name)
	// if err != nil { return nil, err }
	return &u, nil
}
// 4. Interface: Wire everything together (e.g., HTTP Handler)
// File: interface/http_handler.go
package httpinterface

import (
	"encoding/json"
	"net/http"
	"yourmodule/application"
	"yourmodule/domain"
)

func NewHTTPHandler(repo domain.UserRepository) http.Handler {
	service := &application.UserService{repo: repo}
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		user, err := service.GetUser(r.URL.Query().Get("id"))
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		json.NewEncoder(w).Encode(user)
	})
}

To run your application, initialize the concrete infrastructure components in main.go and pass them to the interface layer to create the final handler.