Implementing the repository pattern in Go with both in-memory and MySQL repositories

RMAG news

– We define the User struct representing a user entity.
– We define the UserRepository interface with methods for managing users.
– We implement InMemoryUserRepository and MySQLUserRepository to provide in-memory and MySQL-based repositories, respectively.
– NewInMemoryUserRepository and NewMySQLUserRepository are constructor functions for creating instances of the respective repositories.
– We demonstrate how to use both repositories in the main function by inserting users, getting a user by ID, and getting all users.

package main

import (
“database/sql”
“errors”
“fmt”

_ “github.com/go-sql-driver/mysql”
)

// User represents a user entity
type User struct {
ID int
Username string
Email string
}

// UserRepository defines the methods a user repository must implement
type UserRepository interface {
Insert(user *User) error
GetByID(id int) (*User, error)
GetAll() ([]*User, error)
}

// InMemoryUserRepository is an in-memory implementation of UserRepository
type InMemoryUserRepository struct {
users []*User
}

// NewInMemoryUserRepository creates a new instance of InMemoryUserRepository
func NewInMemoryUserRepository() *InMemoryUserRepository {
return &InMemoryUserRepository{
users: make([]*User, 0),
}
}

// Insert inserts a new user into the repository
func (repo *InMemoryUserRepository) Insert(user *User) error {
repo.users = append(repo.users, user)
return nil
}

// GetByID retrieves a user by its ID from the repository
func (repo *InMemoryUserRepository) GetByID(id int) (*User, error) {
for _, user := range repo.users {
if user.ID == id {
return user, nil
}
}
return nil, errors.New(“user not found”)
}

// GetAll retrieves all users from the repository
func (repo *InMemoryUserRepository) GetAll() ([]*User, error) {
return repo.users, nil
}

// MySQLUserRepository is a MySQL implementation of UserRepository
type MySQLUserRepository struct {
db *sql.DB
}

// NewMySQLUserRepository creates a new instance of MySQLUserRepository
func NewMySQLUserRepository(dataSourceName string) (*MySQLUserRepository, error) {
db, err := sql.Open(“mysql”, dataSourceName)
if err != nil {
return nil, err
}
return &MySQLUserRepository{
db: db,
}, nil
}

// Insert inserts a new user into the MySQL repository
func (repo *MySQLUserRepository) Insert(user *User) error {
_, err := repo.db.Exec(“INSERT INTO users (id, username, email) VALUES (?, ?, ?)”, user.ID, user.Username, user.Email)
if err != nil {
return err
}
return nil
}

// GetByID retrieves a user by its ID from the MySQL repository
func (repo *MySQLUserRepository) GetByID(id int) (*User, error) {
row := repo.db.QueryRow(“SELECT id, username, email FROM users WHERE id = ?”, id)
user := &User{}
err := row.Scan(&user.ID, &user.Username, &user.Email)
if err != nil {
return nil, err
}
return user, nil
}

// GetAll retrieves all users from the MySQL repository
func (repo *MySQLUserRepository) GetAll() ([]*User, error) {
rows, err := repo.db.Query(“SELECT id, username, email FROM users”)
if err != nil {
return nil, err
}
defer rows.Close()

var users []*User
for rows.Next() {
user := &User{}
err := rows.Scan(&user.ID, &user.Username, &user.Email)
if err != nil {
return nil, err
}
users = append(users, user)
}
return users, nil
}

func main() {
// Example usage of in-memory repository
memRepo := NewInMemoryUserRepository()
memRepo.Insert(&User{ID: 1, Username: “user1”, Email: “user1@example.com”})
memRepo.Insert(&User{ID: 2, Username: “user2”, Email: “user2@example.com”})

user, err := memRepo.GetByID(1)
if err != nil {
fmt.Println(“Error:”, err)
} else {
fmt.Println(“In-Memory User:”, user)
}

allUsers, err := memRepo.GetAll()
if err != nil {
fmt.Println(“Error:”, err)
} else {
fmt.Println(“In-Memory All Users:”, allUsers)
}

// Example usage of MySQL repository
mysqlRepo, err := NewMySQLUserRepository(“user:password@tcp(127.0.0.1:3306)/database_name”)
if err != nil {
fmt.Println(“Error:”, err)
return
}

mysqlRepo.Insert(&User{ID: 3, Username: “user3”, Email: “user3@example.com”})
mysqlRepo.Insert(&User{ID: 4, Username: “user4”, Email: “user4@example.com”})

user, err = mysqlRepo.GetByID(3)
if err != nil {
fmt.Println(“Error:”, err)
} else {
fmt.Println(“MySQL User:”, user)
}

allUsers, err = mysqlRepo.GetAll()
if err != nil {
fmt.Println(“Error:”, err)
} else {
fmt.Println(“MySQL All Users:”, allUsers)
}
}

Leave a Reply

Your email address will not be published. Required fields are marked *