go-clean

module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 27, 2019 License: MIT

README

go-clean-architecture

Built a clean architecture using Golang.

Example

Adapter

It describes the processing of controller for calling by routing.

package userscontroller

import (
    "encoding/json"
    "log"
    "net/http"
    "strconv"

    "github.com/gorilla/mux"
    "github.com/RikiyaFujii/go-clean/src/adapter/errorlog"
    "github.com/RikiyaFujii/go-clean/src/entity"
    "github.com/RikiyaFujii/go-clean/src/infrastructure/database"
    "github.com/RikiyaFujii/go-clean/src/infrastructure/user"
    "github.com/RikiyaFujii/go-clean/src/usecase"
)

// UserController ...
type UserController struct {
    Interactor usecase.UserInteractor
}

// NewUserController ...
func NewUserController(sqlHandler database.SQLHandler) *UserController {
    return &UserController{
        Interactor: usecase.UserInteractor{
            UserRepository: &user.UserImpl{
                SQLHandler: sqlHandler,
            },
        },
    }
}

// Create ...
func (c *UserController) Create(w http.ResponseWriter, r *http.Request) {
    u := entity.User{}
    err := json.NewDecoder(r.Body).Decode(&u)
    errorlog.ErrorStatus(w, err, http.StatusBadRequest)
    err = c.Interactor.Store(u)
    errorlog.ErrorStatus(w, err, http.StatusInternalServerError)
    log.Println("Created User!!")
}
package errorlog

import (
    "log"
    "net/http"
)

// ErrorStatus ...
func ErrorStatus(w http.ResponseWriter, err error, status int) {
    if err != nil {
        log.Println("Error: ", err)
        w.WriteHeader(status)
        return
    }
}
DB

It is a layer for migration and has DDL statements and migration files.

-- +goose Up
-- SQL in section 'Up' is executed when this migration is applied
CREATE TABLE `users`(
    `id` INT (11) NOT NULL AUTO_INCREMENT,
    `first_name` VARCHAR(256) NOT NULL,
    `last_name` VARCHAR(256) NOT NULL,
    PRIMARY KEY(`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;

-- +goose Down
-- SQL section 'Down' is executed when this migration is rolled back
DROP TABLE `users`;
development:
    driver: mysql
    open: root:@/clean_go?parseTime=true&charset=utf8mb4&interpolateParams=true
Entity

A data structure describing business rules.

package entity

// User ...
type User struct {
    ID        int    `json:"id" db:"id"`
    FirstName string `json:"first_name" db:"first_name"`
    LastName  string `json:"last_name" db:"last_name"`
}
External

Call controller on layer describing API routing.

package external

import (
    "github.com/gorilla/mux"
    "github.com/RikiyaFujii/go-clean/src/adapter/userscontroller"
    "github.com/RikiyaFujii/go-clean/src/infrastructure/database"
)

// Router ...
func Router(r *mux.Router) {
    usersController := userscontroller.NewUserController(*database.NewSQLHandler())
    r.HandleFunc("/users", usersController.Create).Methods("POST")
}
Infrastructure

Definition of interface handled by Handler, Model layer (impl), Model for accessing DB.

package interfaces

import (
    "database/sql"
)

// SQLHandler ...
type SQLHandler interface {
    Prepare(string) (*sql.Stmt, error)
}
package interfaces

import (
    "github.com/RikiyaFujii/go-clean/src/entity"
)

// UserRepository ...
type UserRepository interface {
    Store(entity.User) error
}
package database

import (
    "database/sql"

    _ "github.com/go-sql-driver/mysql"
    "github.com/jmoiron/sqlx"
)

// SQLHandler ...
type SQLHandler struct {
    Conn *sqlx.DB
}

// NewSQLHandler ...
func NewSQLHandler() *SQLHandler {
    ctx, err := sqlx.Open("mysql", "root:@/clean_go?parseTime=true&charset=utf8mb4&interpolateParams=true")
    if err != nil {
        panic(err)
    }
    sqlHandler := new(SQLHandler)
    sqlHandler.Conn = ctx
    return sqlHandler
}

// Prepare ...
func (s *SQLHandler) Prepare(query string) (*sql.Stmt, error) {
    result, err := s.Conn.Prepare(query)
    if err != nil {
        return nil, err
    }
    return result, nil
}
package user

import (
    "github.com/RikiyaFujii/go-clean/src/entity"
    "github.com/RikiyaFujii/go-clean/src/infrastructure/database"
)

// UserImpl ...
type UserImpl struct {
    database.SQLHandler
}

// Store ...
func (ui *UserImpl) Store(u entity.User) error {
    ctx := database.NewSQLHandler()
    res, err := ctx.Prepare(
        `INSERT INTO users (first_name, last_name) VALUES(?, ?)`,
    )
    if err != nil {
        return err
    }
    defer res.Close()

    _, err = res.Exec(u.FirstName, u.LastName)
    return err
}
Usecase

Includes application-specific business rules. Encapsulate and implement all system use cases.

package usecase

import (
    "github.com/RikiyaFujii/go-clean/src/entity"
    "github.com/RikiyaFujii/go-clean/src/infrastructure/interfaces"
)

// UserInteractor ...
type UserInteractor struct {
    UserRepository interfaces.UserRepository
}

// Store ...
func (ui *UserInteractor) Store(u entity.User) error {
    err := ui.UserRepository.Store(u)
    if err != nil {
        return err
    }
    return nil
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL