Repository Pattern Implementation with Go

Last updated Oct 26, 2021

Repository pattern is a common design pattern that used to develop many applications like web based or mobile based application. In this article, the repository pattern is implemented in Go programming language. This pattern is implemented to develop console-based application to manage products data.

 

What is Repository Pattern

Repository pattern is software design pattern that usually consist of many components including repository, service and client.

  • Repository: This component is used to access directly into the storage. This storage can be local storage or database.

  • Service: This component is used to execute some functions from repository. This component acts as a "bridge" between the client and the repository.

  • Client: This component is used to execute some functions from client so the client only take care what is needed to be used.

The repository pattern is illustrated in this picture.

Repository Pattern Structure

 

Create a Project

Create a Go project with this command. The domain name can be customized based on your repository.

go mod init github.com/nadirbasalamah/go-products

Install dependency to create an id.

go get github.com/google/uuid

Create some directories called model, repository, service and client.

 

Create a Model

Inside model directory, create new file called product.go. In this file, the struct that represents the product entity is created.

package model

// Product represents product entity
type Product struct {
    Id          string
    Name        string
    Description string
    Price       float64
    Stock       int
}

In the same directory, create a new file called productInput.go. In this file, the struct that used to add or update product data is created.

package model

// ProductInput represents input for product data
type ProductInput struct {
    Name        string
    Description string
    Price       float64
    Stock       int
}

 

Create a Repository

Inside repository directory, create a new file called repository.go. In this file, the repository component is created to access directly into the storage. The storage that is used is a simple local storage using slice. All the CRUD functionalities that related to product data are created.

package repository

import (
    "github.com/google/uuid"
    "github.com/nadirbasalamah/go-products/model"
)


// create local storage

var database []model.Product = []model.Product{}

// GetProducts returns all products
func GetProducts() []model.Product {
    return database
}


// GetProductById returns product data by ID

func GetProductById(id string) (int, model.Product) {
    var product model.Product
    var productIndex int

    for index, v := range database {
        if v.Id == id {
            product = v
            productIndex = index
        }
    }

    return productIndex, product
}


// AddProduct to add new product data

func AddProduct(productInput model.ProductInput) model.Product {
    var newProduct model.Product = model.Product{
        Id:          uuid.NewString(),
        Name:        productInput.Name,
        Description: productInput.Description,
        Price:       productInput.Price,
        Stock:       productInput.Stock,
    }

    database = append(database, newProduct)
    return newProduct
}


// UpdateProduct to update product data

func UpdateProduct(id string, productInput model.ProductInput) model.Product {
    index, product := GetProductById(id)

    product.Name = productInput.Name
    product.Description = productInput.Description
    product.Price = productInput.Price
    product.Stock = productInput.Stock

    database[index] = product

    return product
}


// DeleteProduct to delete product data

func DeleteProduct(id string) bool {
    var afterDeleted []model.Product = []model.Product{}

    for _, v := range database {
        if v.Id != id {
            afterDeleted = append(afterDeleted, v)
        }
    }

    database = afterDeleted

    return true
}

 

Create a Service

Inside service directory, create a new file called service.go. In this file, the service component is created to use all the functionalities from the repository component.

package service

import (
    "github.com/nadirbasalamah/go-products/model"
    "github.com/nadirbasalamah/go-products/repository"
)

// GetProducts returns all products
func GetProducts() []model.Product {
    return repository.GetProducts()
}

// GetProductById returns product by ID
func GetProductById(id string) (int, model.Product) {
    productIndex, product := repository.GetProductById(id)
    return productIndex, product
}

// AddProduct returns added product
func AddProduct(productInput model.ProductInput) model.Product {
    return repository.AddProduct(productInput)
}

// UpdateProduct returns updated product
func UpdateProduct(id string, productInput model.ProductInput) model.Product {
    return repository.UpdateProduct(id, productInput)
}

// DeleteProduct returns delete result
func DeleteProduct(id string) bool {
    return repository.DeleteProduct(id)
}

Create a Client

Inside client directory, create a new file called client.go. In this file, the client application is created that is using service component.

package client

import (
    "bufio"
    "fmt"
    "os"

    "github.com/nadirbasalamah/go-products/model"
    "github.com/nadirbasalamah/go-products/service"
)

// display the main menu
func DisplayMenu() {
    var choice int
    fmt.Println("Products Manager App")
    fmt.Println("Please choose the menu")
    for {
        fmt.Println("1. Get all products")
        fmt.Println("2. Get Product by ID")
        fmt.Println("3. Add new product")
        fmt.Println("4. Update product")
        fmt.Println("5. Delete product")
        fmt.Println("6. Quit")
        fmt.Scanln(&choice)

        switch choice {
        case 1:
            getAllProducts()
        case 2:
            getProductById()
        case 3:
            addProduct()
        case 4:
            updateProduct()
        case 5:
            deleteProduct()
        case 6:
            fmt.Println("Good bye..")
            return
        default:
            fmt.Println("Input invalid!")
            fmt.Println("Please choose from 1-6")
        }
    }
}

// retrieve all products
func getAllProducts() {
    var products []model.Product = service.GetProducts()

    if len(products) != 0 {
        fmt.Println("All products")
        for _, product := range products {
            showProductData(product)
        }
    } else {
        fmt.Println("No products found!")
    }
}

// retrieve product data by ID
func getProductById() {
    var productId string
    fmt.Println("Enter product ID: ")
    fmt.Scanln(&productId)

    _, product := service.GetProductById(productId)

    fmt.Println("Product data")
    showProductData(product)
}

// add new product
func addProduct() {
    var reader *bufio.Reader = bufio.NewReader(os.Stdin)

    var name, description string
    var price float64
    var stock int

    fmt.Println("Enter product name: ")
    name, _ = reader.ReadString('\n')

    fmt.Println("Enter product description: ")
    description, _ = reader.ReadString('\n')

    fmt.Println("Enter product price: ")
    fmt.Scanf("%f\n", &price)

    fmt.Println("Enter product stock: ")
    fmt.Scanf("%d\n", &stock)

    var newProduct model.ProductInput = model.ProductInput{
        Name:        name,
        Description: description,
        Price:       price,
        Stock:       stock,
    }

    var insertedProduct = service.AddProduct(newProduct)

    fmt.Println("Your inserted product")
    showProductData(insertedProduct)
}

// update product data
func updateProduct() {
    var reader *bufio.Reader = bufio.NewReader(os.Stdin)

    var productId, name, description string
    var price float64
    var stock int

    fmt.Println("Enter product id: ")
    fmt.Scanf("%s\n", &productId)

    fmt.Println("Enter product name: ")
    name, _ = reader.ReadString('\n')

    fmt.Println("Enter product description: ")
    description, _ = reader.ReadString('\n')

    fmt.Println("Enter product price: ")
    fmt.Scanf("%f\n", &price)

    fmt.Println("Enter product stock: ")
    fmt.Scanf("%d\n", &stock)

    var productData model.ProductInput = model.ProductInput{
        Name:        name,
        Description: description,
        Price:       price,
        Stock:       stock,
    }

    var updatedProduct = service.UpdateProduct(productId, productData)

    fmt.Println("Your updated data")
    showProductData(updatedProduct)
}

// delete product data
func deleteProduct() {
    var productId string
    fmt.Println("Enter product id: ")
    fmt.Scanf("%s\n", &productId)

    var isDeleted bool = service.DeleteProduct(productId)

    if isDeleted {
        fmt.Println("Data deleted!")
    }
}

// display product data
func showProductData(product model.Product) {
    fmt.Println("========================")
    fmt.Println("ID: ", product.Id)
    fmt.Println("Name: ", product.Name)
    fmt.Println("Description: ", product.Description)
    fmt.Println("Price: ", product.Price)
    fmt.Println("Stock: ", product.Stock)
    fmt.Println("========================")
}

Use the Client

The client is already created. Use the client in main.go file.

package main

import (
    "github.com/nadirbasalamah/go-products/client"
)

func main() {
    client.DisplayMenu()
}

 

Run the Application

The repository pattern implementation is finished. Run the application using go run main.go command.

Add new product

Products Manager App
Please choose the menu
1. Get all products
2. Get Product by ID
3. Add new product
4. Update product
5. Delete product
6. Quit
3
Enter product name:
macbook
Enter product description:
cool macbook
Enter product price:
299
Enter product stock:
1000
Your inserted product
========================
ID:  b5e9ff7f-d87c-4b97-a3b8-9660da983752
Name:  macbook

Description:  cool macbook

Price:  299
Stock:  1000
========================

Get all products

1. Get all products
2. Get Product by ID
3. Add new product
4. Update product
5. Delete product
6. Quit
1
All products
========================
ID:  b5e9ff7f-d87c-4b97-a3b8-9660da983752
Name:  macbook

Description:  cool macbook

Price:  299
Stock:  1000
========================
========================
ID:  2f43132a-1ff9-4315-b5d7-941976cef6b2
Name:  ps5

Description:  new gaming console

Price:  298
Stock:  100
========================

Get product by ID

1. Get all products
2. Get Product by ID
3. Add new product
4. Update product
5. Delete product
6. Quit
2
Enter product ID:
b5e9ff7f-d87c-4b97-a3b8-9660da983752
Product data
========================
ID:  b5e9ff7f-d87c-4b97-a3b8-9660da983752
Name:  macbook

Description:  cool macbook

Price:  299
Stock:  1000
========================

Update product data

1. Get all products
2. Get Product by ID
3. Add new product
4. Update product
5. Delete product
6. Quit
4
Enter product id:
b5e9ff7f-d87c-4b97-a3b8-9660da983752
Enter product name:
macbook pro
Enter product description:
newest macbook
Enter product price:
1200
Enter product stock:
99
Your updated data
========================
ID:  b5e9ff7f-d87c-4b97-a3b8-9660da983752
Name:  macbook pro

Description:  newest macbook

Price:  1200
Stock:  99
========================

Delete product data

1. Get all products
2. Get Product by ID
3. Add new product
4. Update product
5. Delete product
6. Quit
5
Enter product id:
f78057cf-c3d8-4ab-a642-e9cadf495896
Data deleted!

I hope this article is helpful to learn the implementation of repository pattern in Go programming language.

Article Contributed By :
https://www.rrtutors.com/site_assets/profile/assets/img/avataaars.svg

1145 Views