Architectural Patterns in Go: How Not to Drown in Goroutines

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction: Why Architecture Is Not a Luxury, But a Necessity

\n\n

When you first start writing in Go, everything seems simple: goroutines are flying, channels are humming, and the compiler delights with speed. But a month or two passes, and your pet project turns into a monster with a package main of 3000 lines and prayers of "just don't let it crash." Sound familiar?

\n\n

Go provides powerful tools but doesn't impose rigid frameworks. This is both a plus and a minus. Without a clear architecture, you'll quickly get lost in your own goroutines. This is where architectural patterns in Go come to the rescue — proven solutions to typical design problems.

\n\n

In this article, we'll break down four key patterns that will really simplify your life: Repository, Service Layer, Worker Pool, and Pipeline. You'll see code examples, understand when to apply each pattern, and be able to immediately implement them in your projects. Let's go!

\n\n

1. Repository Pattern: Separating Business Logic from the Database

\n\n

The first pattern every Go developer should master is Repository. Its essence is simple: create a layer between business logic and the data store (DB, files, external APIs).

\n\n

Why is this needed?

\n
    \n
  • Testability: you can easily replace the real database with a mock.
  • \n
  • Flexibility: migrating from PostgreSQL to MongoDB? Just change the repository.
  • \n
  • Code cleanliness: the handler doesn't know where the data comes from — that's the repository's job.
  • \n
\n\n

Implementation Example

\n

Let's say we have a user model:

\n\n
type User struct {\n    ID    int64\n    Name  string\n    Email string\n}
\n\n

Define the repository interface:

\n\n
type UserRepository interface {\n    GetByID(ctx context.Context, id int64) (*User, error)\n    Create(ctx context.Context, user *User) error\n    Update(ctx context.Context, user *User) error\n    Delete(ctx context.Context, id int64) error\n}
\n\n

And its implementation for PostgreSQL:

\n\n
type PostgresUserRepo struct {\n    db *sql.DB\n}\n\nfunc (r *PostgresUserRepo) GetByID(ctx context.Context, id int64) (*User, error) {\n    user := &User{}\n    err := r.db.QueryRowContext(ctx, "SELECT id, name, email FROM users WHERE id = $1", id).\n        Scan(&user.ID, &user.Name, &user.Email)\n    if err != nil {\n        return nil, fmt.Errorf("get user by id: %w", err)\n    }\n    return user, nil\n}
\n\n

Now your handler or service works only with the UserRepository interface, not with a specific database. This is the Repository architectural pattern in Go in action.

\n\n

2. Service Layer: Business Logic Under Control

\n\n

If Repository is responsible for data, then Service Layer is responsible for business rules. This pattern gathers scattered operations into meaningful actions.

\n\n

The Problem Without Service Layer

\n

I often see code where the handler does everything: validates the request, checks permissions, writes to the database, and logs. This violates the Single Responsibility Principle (SRP).

\n\n

How to Fix It?

\n

Introduce a service layer:

\n\n
type UserService interface {\n    Register(ctx context.Context, name, email string) (*User, error)\n    GetProfile(ctx context.Context, userID int64) (*User, error)\n}\n\ntype userService struct {\n    repo UserRepository\n    mail MailSender\n}\n\nfunc (s *userService) Register(ctx context.Context, name, email string) (*User, error) {\n    // 1. Validation\n    if name == "" || email == "" {\n        return nil, ErrInvalidInput\n    }\n\n    // 2. Business logic: check if email is already taken\n    existing, _ := s.repo.GetByEmail(ctx, email)\n    if existing != nil {\n        return nil, ErrEmailAlreadyExists\n    }\n\n    // 3. Create the user\n    user := &User{Name: name, Email: e                

Blogs

Book Recommendations