DEV Community

Permpoon Chao
Permpoon Chao

Posted on

Interface and DB in golang

As implement hexagonal pattern (Ports and adapters pattern), our code should separate to three sections

  1. API (Application Programming Interface) such your inbound (Gin, Echo, Fiber ...), Serialization or something else
  2. Domain, Entity or something else that make your app unique
  3. SPI (Service Programming Interface) such as external service, DB, DAO (Data Access Object) or something else

Example with below code, This will show relation with My Entity (Todo) and SPI(Database Insert)

  1. Entity -> Todo struct
  2. Port -> TodoHandler
  3. Adapters -> todoAdapter interface, MySQLDB and MongoDB struct
package main

import (
    "log"

    "go.mongodb.org/mongo-driver/mongo"
    "gorm.io/gorm"
)

type Todo struct {
    ID          string
    Title       string
    Description string
}

type todoAdapter interface {
    Create(*Todo) error
}

type TodoHandler struct {
    adapter todoAdapter
}

type MySQLDB struct {
    db *gorm.DB
}

type MongoDB struct {
    db *mongo.Collection
}

func NewTodoHandler(adapter todoAdapter) *TodoHandler {
    return &TodoHandler{adapter: adapter}
}

func (db *MySQLDB) Create(todo *Todo) error {
    log.Println("🐟 MySQL Create Interface")

    // in real example, you can comment out below code
    // err := db.db.Create(todo)
    // return err

    return nil
}

func NewMySQLDB(db *gorm.DB) *MySQLDB {
    return &MySQLDB{db: db}
}

func (db *MongoDB) Create(todo *Todo) error {
    log.Println("✅ MongoDB Create Interface")

    // in real example, you can comment out below code
    // _, err := db.db.InsertOne(context.TODO(), todo)
    // return err

    return nil
}

func NewMongoDB(db *mongo.Collection) *MongoDB {
    return &MongoDB{db: db}
}

func main() {
    var todoHandler *TodoHandler

    // Todo insert with MySQL
    mysqlAdapter := NewMySQLDB(&gorm.DB{})
    todoHandler = NewTodoHandler(mysqlAdapter)
    todoHandler.adapter.Create(&Todo{
        ID: "1", Title: "New note", Description: "Save in mysql",
    })

    // Todo insert with MongoDB
    mongoAdapter := NewMongoDB(&mongo.Collection{})
    todoHandler = NewTodoHandler(mongoAdapter)
    todoHandler.adapter.Create(&Todo{
        ID: "1", Title: "New note", Description: "Save in mongo",
    })
}

Enter fullscreen mode Exit fullscreen mode

In the example, you will see two adapters should implement Create method to related with adapter interface

And result will be like this

2022/03/06 15:35:46 🐟 MySQL Create Interface
2022/03/06 15:35:46 ✅ MongoDB Create Interface
Enter fullscreen mode Exit fullscreen mode

Top comments (0)