Golang 및 Clean Archeitecture로 API 서버 구축
의 목적
나는 실제 클린 아케텍처 개발 상황에서 어떤 구조를 구축해 쉽게 개발할 수 있는지 설계했다.
나는 실천을 구상하여 구축을 고려하고 있다.API 문서가 아닌 sawagger를 구현했습니다.
사용할 도구
디렉토리 구조
├─ docker/
├─ api
└─ environments
├─ production/
├─ development/
└─ test/
├─ document
└─ mysql
├─ documents/
└─ design/
├─ server/
├─ adapters/
├─ controllers/
├─ gateways/
└─ presenter/
├─ infrastructure/
├─ routes/
└─ database/
├─ usecases/
├─ entities/
└─ main.go
└─ docker-compose.development.yml
환경 정보
docker-compose로 컨테이너를 관리합니다.컨테이너의 내용은 다음과 같다.
Clean Archeitecture 정보
이번에는 녹색 구조를 따라 어떤 목록 구성에서 어떤 역할을 하고 있는지만 설명했다.청결 구조를 스스로 조사하세요.
Adapters
이 디렉터리는 외부 통신과의 처리를 실시했다.
package guest
import (
gateway "api/server/adapters/gateways"
usecase "api/server/usecases/guest"
"github.com/labstack/echo/v4"
"strconv"
)
type GuestController struct {
Interactor usecase.GuestInteractor
}
func InitGuestController(sqlHandler gateway.SQLHandler) *GuestController {
return &GuestController{
Interactor: usecase.GuestInteractor{
GuestPort: &gateway.GuestRepository{
SQLHandler: sqlHandler,
},
},
}
}
func (controller *GuestController) Show(c echo.Context) (err error) {
id, _ := strconv.Atoi(c.Param("id"))
guest, err := controller.Interactor.GuestByID(id)
if err != nil {
c.JSON(500, err)
return
}
c.JSON(200, guest)
return
}
func (controller *GuestController) Index(c echo.Context) (err error) {
guests, err := controller.Interactor.Guests()
if err != nil {
c.JSON(500, err)
return
}
c.JSON(200, guests)
return
package gateways
import (
"api/server/entities"
)
type GuestRepository struct {
SQLHandler
}
func (repo *GuestRepository) FindByID(id int) (guest entities.Guest, err error) {
if err = repo.Find(&guest, id).Error; err != nil {
return
}
return
}
func (repo *GuestRepository) FindAll() (guests entities.Guests, err error) {
if err = repo.Find(&guests).Error; err != nil {
return
}
return
}
sqlhandler.gopackage gateways
import (
"gorm.io/gorm"
)
type SQLHandler interface {
First(interface{}, ...interface{}) *gorm.DB
Last(interface{}, ...interface{}) *gorm.DB
Take(interface{}, ...interface{}) *gorm.DB
Find(interface{}, ...interface{}) *gorm.DB
}
Infrastructures
이 디렉터리는 응용 프로그램 외부로 통신하는 처리에 사용됩니다.
├─ infrastructure/
├─ routes/
└─ guest.go
└─ route.go
route.gopackage infrastructure
import (
"api/server/infrastructure/routes"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
)
func Run() {
e := echo.New()
e.Use(middleware.Logger())
e.Use(middleware.Recover())
e.Use(middleware.CORS())
routes.InitGuest(e)
e.Logger.Fatal(e.Start(":1323"))
}
guest.gopackage routes
import (
controller "api/server/adapters/controllers/guest"
"api/server/infrastructure/database"
"github.com/labstack/echo/v4"
)
func InitGuest(e *echo.Echo) {
guestController := controller.InitGuestController(database.InitSQLHandler())
e.GET("/guests/:id", func(c echo.Context) error { return guestController.Show(c) })
e.GET("/guests", func(c echo.Context) error { return guestController.Index(c) })
}
package database
import (
"fmt"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
"log"
"os"
"time"
"api/server/adapters/gateways"
)
type SQLHandler struct {
db *gorm.DB
}
func InitSQLHandler() gateways.SQLHandler {
user := os.Getenv("DB_USER")
pass := os.Getenv("DB_PASSWORD")
containerName := os.Getenv("DB_CONTAINER_NAME")
port := os.Getenv("DB_PORT")
dbName := os.Getenv("DB_NAME")
newLogger := logger.New(
log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
logger.Config{
SlowThreshold: time.Second, // Slow SQL threshold
LogLevel: logger.Info, // Log level
IgnoreRecordNotFoundError: true, // Ignore ErrRecordNotFound error for logger
Colorful: false, // Disable color
},
)
dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s", user, pass, containerName, port, dbName)
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
Logger: newLogger,
})
if err != nil {
panic(err)
}
sqlHandler := new(SQLHandler)
sqlHandler.db = db
return sqlHandler
}
func (handler *SQLHandler) First(out interface{}, where ...interface{}) *gorm.DB {
return handler.db.First(out, where...)
}
func (handler *SQLHandler) Take(out interface{}, where ...interface{}) *gorm.DB {
return handler.db.Take(out, where...)
}
func (handler *SQLHandler) Last(out interface{}, where ...interface{}) *gorm.DB {
return handler.db.Last(out, where...)
}
func (handler *SQLHandler) Find(out interface{}, where ...interface{}) *gorm.DB {
return handler.db.Find(out, where...)
}
Usecases
usecases/
└─ guest
├─ interactor.go
└─ port.go
interactor.gopackage guest
import (
"api/server/entities"
)
type GuestInteractor struct {
GuestPort GuestPort
}
func (interactor *GuestInteractor) GuestByID(id int) (guest entities.Guest, err error) {
guest, err = interactor.GuestPort.FindByID(id)
return
}
func (interactor *GuestInteractor) Guests() (guests entities.Guests, err error) {
guests, err = interactor.GuestPort.FindAll()
return
}
port.gopackage guest
import (
"api/server/entities"
)
type GuestPort interface {
FindByID(id int) (entities.Guest, error)
FindAll() (entities.Guests, error)
}
Entities
package entities
type Guests []Guest
type Guest struct {
ID int `json:"id" param:"id"`
FirstName string `json:"first_name"`
FirstNameKana string `json:"first_name_kana"`
LastName string `json:"last_name"`
LastNameKana string `json:"last_name_kana"`
Gender int `json:"gender"`
Birthday string `json:"birthday"`
Tel int `json:"tel"`
Email string `json:"email"`
}
최후
여기까지 읽어주셔서 감사합니다.
나는 이번 실시가 단지 하나의 생각일 뿐이라고 생각한다.좋은 생각과 개선점이 있는 사람이 의견을 얻었으면 좋겠어요.
이번 구성은 이 페이지에 있으니 관심 있는 사람은 반드시 시도해 보세요.
Reference
이 문제에 관하여(Golang 및 Clean Archeitecture로 API 서버 구축), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/yantera/articles/524591655e3244텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)