CODESAMPLE

N-tier - Go

Share on:

The N-tier pattern organizes an application into distinct layers, each with a specific responsibility. This promotes separation of concerns, making the application more maintainable, testable, and scalable. A typical N-tier architecture includes a presentation tier (UI), a business logic tier, and a data access tier.

This Go example demonstrates a simple 3-tier architecture for managing user data. The main.go file represents the presentation tier, handling user interaction (in this case, just printing). The user_service.go file contains the business logic for creating and retrieving users. Finally, user_repository.go handles the data access, interacting with an in-memory user store. Using interfaces (UserRepository) allows for easy swapping of data storage mechanisms without affecting higher tiers, a key benefit of the pattern. This structure aligns with Go’s emphasis on composability and clear interfaces.

// main.go
package main

import (
	"fmt"
)

func main() {
	repo := &InMemoryUserRepository{users: make(map[int]string)}
	service := &UserService{repo: repo}

	userID := service.CreateUser("Alice")
	userName := service.GetUser(userID)

	fmt.Printf("User ID: %d, Name: %s\n", userID, userName)
}

// user_service.go
package main

type UserService struct {
	repo UserRepository
}

func (s *UserService) CreateUser(name string) int {
	return s.repo.Save(name)
}

func (s *UserService) GetUser(id int) string {
	return s.repo.Get(id)
}

// user_repository.go
package main

type UserRepository interface {
	Save(name string) int
	Get(id int) string
}

type InMemoryUserRepository struct {
	users map[int]string
	nextID int
}

func (r *InMemoryUserRepository) Save(name string) int {
	r.nextID++
	r.users[r.nextID] = name
	return r.nextID
}

func (r *InMemoryUserRepository) Get(id int) string {
	return r.users[id]
}