xiaohongshu
xiaohongshu
go-clean-architecture
Expert knowledge in Go clean architecture patterns and best practices
Full skill instructions
Clean Architecture in Go emphasizes separation of concerns through distinct layers, with dependencies pointing inward toward the domain.
Location: internal/domain/
Contains:
Rules:
Example:
// internal/domain/account.go
package domain
type Account struct {
ID string
Name string
Type AccountType
Balance int // cents
}
type AccountRepository interface {
Create(account *Account) error
GetByID(id string) (*Account, error)
Update(account *Account) error
Delete(id string) error
}
// Domain validation
func (a *Account) Validate() error {
if a.Name == "" {
return ErrInvalidName
}
if !a.Type.IsValid() {
return ErrInvalidType
}
return nil
}
Location: internal/application/
Contains:
Rules:
Example:
// internal/application/account_service.go
package application
import "internal/domain"
type AccountService struct {
repo domain.AccountRepository // Interface, not concrete type
}
func NewAccountService(repo domain.AccountRepository) *AccountService {
return &AccountService{repo: repo}
}
func (s *AccountService) CreateAccount(account *domain.Account) error {
if err := account.Validate(); err != nil {
return fmt.Errorf("validation failed: %w", err)
}
if err := s.repo.Create(account); err != nil {
return fmt.Errorf("failed to create account: %w", err)
}
return nil
}
Location: internal/infrastructure/
Contains:
Rules:
Example:
// internal/infrastructure/repository/account_repository.go
package repository
import (
"database/sql"
"internal/domain"
)
type AccountRepository struct {
db *sql.DB
}
func NewAccountRepository(db *sql.DB) *AccountRepository {
return &AccountRepository{db: db}
}
func (r *AccountRepository) Create(account *domain.Account) error {
query := `INSERT INTO accounts (id, name, type, balance) VALUES (?, ?, ?, ?)`
_, err := r.db.Exec(query, account.ID, account.Name, account.Type, account.Balance)
return err
}
// internal/infrastructure/http/handlers/account_handler.go
package handlers
type AccountHandler struct {
service *application.AccountService
}
func (h *AccountHandler) CreateAccount(w http.ResponseWriter, r *http.Request) {
// 1. Parse request
var req CreateAccountRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, "invalid request", http.StatusBadRequest)
return
}
// 2. Call service
account := req.ToDomain()
if err := h.service.CreateAccount(account); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// 3. Return response
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(account)
}
Wire dependencies in main.go:
// cmd/server/main.go
func main() {
// Infrastructure
db := setupDatabase()
// Repositories (concrete implementations)
accountRepo := repository.NewAccountRepository(db)
// Services (injected with interfaces)
accountService := application.NewAccountService(accountRepo)
// Handlers (injected with services)
accountHandler := handlers.NewAccountHandler(accountService)
// Router
router := setupRouter(accountHandler)
http.ListenAndServe(":8080", router)
}
// Domain defines interface
type Repository interface {
Create(entity *Entity) error
GetByID(id string) (*Entity, error)
}
// Infrastructure implements
type SQLRepository struct {
db *sql.DB
}
func (r *SQLRepository) Create(entity *Entity) error {
// SQL implementation
}
type Service struct {
repo domain.Repository // Depend on interface
}
func (s *Service) DoBusinessLogic(entity *domain.Entity) error {
// Validate
// Transform
// Call repository
return s.repo.Create(entity)
}
func (h *Handler) HandleRequest(w http.ResponseWriter, r *http.Request) {
// Parse → Service → Respond
req := parseRequest(r)
result, err := h.service.Do(req)
respond(w, result, err)
}
// BAD: Domain importing database
import "database/sql"
type Account struct {
db *sql.DB // ❌ Domain shouldn't know about database
}
// BAD: Service with HTTP dependency
func (s *Service) Create(w http.ResponseWriter, r *http.Request) {
// ❌ Service shouldn't handle HTTP
}
// BAD: Service with database dependency
func (s *Service) Create(db *sql.DB, entity *Entity) error {
// ❌ Service should use repository interface
}
// BAD: Complex logic in handler
func (h *Handler) Create(w http.ResponseWriter, r *http.Request) {
// Parse
// ❌ Complex validation
// ❌ Calculations
// ❌ Business rules
// Direct database access
}
// GOOD: Thin handler
func (h *Handler) Create(w http.ResponseWriter, r *http.Request) {
req := parse(r)
result := h.service.Create(req) // Service has the logic
respond(w, result)
}
// BAD: Business rules in repository
func (r *Repository) Create(account *Account) error {
// ❌ Business validation in repository
if account.Balance < 0 && account.Type != "credit" {
return errors.New("invalid")
}
// Should only handle persistence
}
func TestAccount_Validate(t *testing.T) {
// Test entity validation
// No mocks needed
}
func TestService_Create(t *testing.T) {
mockRepo := &MockRepository{} // Mock interface
service := NewService(mockRepo)
// Test business logic
}
func TestRepository_Create(t *testing.T) {
db := setupTestDB() // Real database
repo := NewRepository(db)
// Test persistence
}
func TestHandler_Create(t *testing.T) {
mockService := &MockService{}
handler := NewHandler(mockService)
req := httptest.NewRequest("POST", "/", body)
w := httptest.NewRecorder()
handler.Create(w, req)
// Test HTTP layer
}
✅ Testability: Easy to mock dependencies ✅ Maintainability: Clear separation of concerns ✅ Flexibility: Easy to swap implementations ✅ Independence: Domain logic independent of frameworks ✅ Scalability: Easy to add features
xiaohongshu
technical spec
product ux expert
database patterns
Conduct multi-agent task orchestration and workflow coordination.
Initialize project with Conductor artifacts (product definition,
Expert in web animations, transitions, and motion design using Framer Motion and CSS
Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...
PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.
Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...
Display project status, active tracks, and next actions
Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.
Generate, edit, and beat-sync AI video with leading models in one workspace.
The world's fastest calendar for remote work
Transform Your Design with AI Designer by ImgCreator.ai
Revolutionizing Video Production with AI-Powered Creativity
Extend an image past the frame and let AI fill the new aspect ratio.
Discover your celebrity doppelgänger with StarByFace!
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Opus.ai: Revolutionize Your Web Experience