27.04.2024 в 18:17
Полина Родионова
Реализация паттерна репозитория в Go с репозиториями in-memory и MySQL
- Мы определяем структуру
User
, представляющую сущность пользователя. - Мы определяем интерфейс
UserRepository
с методами для управления пользователями. - Мы реализуем
InMemoryUserRepository
иMySQLUserRepository
для обеспечения хранилищ в памяти и на основе MySQL, соответственно. NewInMemoryUserRepository
иNewMySQLUserRepository
- это функции-конструкторы для создания экземпляров соответствующих репозиториев.- Мы демонстрируем, как использовать оба репозитория в главной функции, вставляя пользователей, получая их по ID и получая информацию обо всех пользователях.
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)
}
}
Благодарю за прочтение! Счастливого кодинга!