Write NEW Golang MICROSERVICES project from my existing Gin+Go+Gorm project that i will piecewisely provide now

With:
+grpc microservices, 
+rabbitmq, 
+protobuf, 

Use:
"API Gateway Pattern"

Restrictions: 
-Use only gin's context
-Create clean architecture (each service is separately in folders)

Write a coherent and tidy code

Below is code of my existing project
Controllers:

package ctrl


import (
  "github.com/badoux/checkmail"
  "github.com/dgrijalva/jwt-go"
  "github.com/gin-gonic/gin"
  "github.com/maulerrr/sample-project/api/db"
  "github.com/maulerrr/sample-project/api/dto"
  "github.com/maulerrr/sample-project/api/models"
  "github.com/maulerrr/sample-project/api/utils"
  "gorm.io/gorm"
  "os"
  "time"
)


func Login(context *gin.Context) {
  credentials := new(dto.Login)


  if err := context.BindJSON(credentials); err != nil {
     utils.SendMessageWithStatus(context, "Invalid JSON", 400)
     return
  }


  user := models.User{}
  query := models.User{Email: credentials.Email}
  err := db.DB.First(&user, &query).Error


  if err == gorm.ErrRecordNotFound {
     utils.SendMessageWithStatus(context, "User not found", 404)
     return
  }


  if !utils.ComparePasswords(user.Password, credentials.Password) {
     utils.SendMessageWithStatus(context, "Password is not correct", 401)
     return
  }


  tokenString, err := GenerateToken(user)


  if err != nil {
     utils.SendMessageWithStatus(context, "Auth error (token creation)", 500)
     return
  }


  response := &models.TokenResponse{
     UserID:   user.UserID,
     Username: user.Username,
     Email:    user.Email,
     Token:    tokenString,
  }


  utils.SendSuccessJSON(context, response)
}


func SignUp(context *gin.Context) {
  json := new(dto.Registration)


  if err := context.BindJSON(json); err != nil {
     utils.SendMessageWithStatus(context, "Invalid JSON", 400)
     return
  }


  if len(json.Password) < 4 {
     utils.SendMessageWithStatus(context, "Minimum password length is 4", 400)
     return
  }


  password := utils.HashPassword([]byte(json.Password))
  err := checkmail.ValidateFormat(json.Email)
  if err != nil {
     utils.SendMessageWithStatus(context, "Invalid Email Address", 400)
     return
  }


  newUser := models.User{
     Password:  password,
     Email:     json.Email,
     Username:  json.Username,
     CreatedAt: time.Now(),
  }


  found := models.User{}
  query := models.User{Email: json.Email}
  err = db.DB.First(&found, &query).Error
  if err != gorm.ErrRecordNotFound {
     utils.SendMessageWithStatus(context, "User already exists", 400)
     return
  }


  err = db.DB.Create(&newUser).Error
  if err != nil {
     utils.SendMessageWithStatus(context, err.Error(), 400)
     return
  }


  tokenString, err := GenerateToken(newUser)


  if err != nil {
     utils.SendMessageWithStatus(context, "Auth error (token creation)", 500)
     return
  }


  response := &models.TokenResponse{
     UserID:   newUser.UserID,
     Username: newUser.Username,
     Email:    newUser.Email,
     Token:    tokenString,
  }


  utils.SendSuccessJSON(context, response)
}


func GenerateToken(user models.User) (string, error) {
  expirationTime := time.Now().Add(time.Hour * 24)


  claims := &models.Claims{
     ID:       user.UserID,
     Email:    user.Email,
     Username: user.Username,
     StandardClaims: jwt.StandardClaims{
        ExpiresAt: expirationTime.Unix(),
     },
  }


  jwtKey := os.Getenv("JWT_KEY")
  token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
  tokenString, err := token.SignedString([]byte(jwtKey))


  return tokenString, err
}


Database:

package db


import (
  "github.com/maulerrr/sample-project/api/models"
  "gorm.io/driver/postgres"
  "gorm.io/gorm"
  "log"
)


var DB *gorm.DB


func ConnectDB() {
  var err error
  //dsn := os.Getenv("DATABASE_DSN")
  dsn := "postgres://postgres:1111@localhost:5432/sample?sslmode=disable"


  //log.Print(dsn)


  DB, err = gorm.Open(
     postgres.Open(dsn),
     &gorm.Config{},
  )


  if err != nil {
     log.Fatal(
        "Failed to connect to the database! \n",
        err,
     )
  }


  //log.Println("Connected to database!")
  //log.Println("Running migrations")


  err = DB.AutoMigrate(
     &models.User{},
     &models.Post{},
     &models.Like{},
     &models.Comment{},
  )


  if err != nil {
     log.Fatal("Failed to connect to migrate! \n", err)
  }


  //log.Println("Migrations done!")
}


DTO:

package dto


type Registration struct {
  Username string `json:"username"`
  Email    string `json:"email"`
  Password string `json:"password"`
}


type Login struct {
  Email    string `json:"email"`
  Password string `json:"password"`
}

Models:

package models


import "time"


type User struct {
  UserID    int       `gorm:"primaryKey" json:"user_id"`
  Username  string    `json:"username"`
  Email     string    `gorm:"unique" json:"email"`
  Password  string    `json:"password"`
  CreatedAt time.Time `json:"created_at"`
}

Routes:

package routes


import (
  "github.com/gin-gonic/gin"
  "github.com/maulerrr/sample-project/api/ctrl"
  "github.com/maulerrr/sample-project/api/middleware"
)


func InitRoutes(app *gin.Engine) {
  router := app.Group("api/v1")


  router.GET("/healthcheck")


  authRouter := router.Group("/auth")
  authRouter.POST("/signup", ctrl.SignUp)
  authRouter.POST("/login", ctrl.Login)


  postRouter := router.Group("/post")
  postRouter.GET("/", middlewares.AuthMiddleware(), ctrl.GetAllPosts)
  postRouter.POST("/", middlewares.AuthMiddleware(), ctrl.AddPost)
  postRouter.GET("/:id", middlewares.AuthMiddleware(), ctrl.GetByPostID)
  postRouter.DELETE("/:user_id/:id", middlewares.PostDeletionMiddleware(), ctrl.DeletePostByID)


  postRouter.POST("/like", middlewares.AuthMiddleware(), ctrl.AddLike)
  postRouter.GET("/like/:user_id/:id", middlewares.AuthMiddleware(), ctrl.GetLike)
  postRouter.GET("/like/count/:id", middlewares.AuthMiddleware(), ctrl.GetLikesCountOnPost)


  commentRouter := router.Group("/comment")
  commentRouter.GET("/:post_id", middlewares.AuthMiddleware(), ctrl.GetAllComments)
  commentRouter.POST("/", middlewares.AuthMiddleware(), ctrl.CreateComment)
  commentRouter.DELETE("/:user_id/:id", middlewares.CommentDeletionMiddleware(), ctrl.DeleteComment)
}

Utils:

package utils


import (
  "golang.org/x/crypto/bcrypt"
)


func HashPassword(pwd []byte) string {
  hash, _ := bcrypt.GenerateFromPassword(pwd, bcrypt.DefaultCost)
  return string(hash)
}


func ComparePasswords(
  hashedPwd string,
  plainPwd string,
) bool {
  byteHash := []byte(hashedPwd)
  bytePlainPsw := []byte(plainPwd)
  err := bcrypt.CompareHashAndPassword(byteHash, bytePlainPsw)


  return err == nil
}

package utils


import (
  "github.com/gin-gonic/gin"
  "net/http"
)


func SendSuccessJSON(c *gin.Context, data interface{}) {
  c.JSON(http.StatusOK, gin.H{
     "code":    200,
     "message": "success",
     "data":    data,
  })
}


func SendMessageWithStatus(c *gin.Context, message string, status int) {
  c.JSON(status, gin.H{
     "code":    status,
     "message": message,
  })
}