Go Gin 프레임워크가 포함된 CRUD api(생산 준비 완료)

This is my second post on GO lang with Gin framework and PostgreSQL. Read my which takes you just 2 mins to setup the project and read env variables using viper!.



이 게시물에서는 PostgreSQL 데이터베이스에서 데이터를 읽기 위해 Library CRUD API를 생성하고 있습니다.
  • 책 추가
  • 책 삭제
  • 책 업데이트
  • ID별 도서 검색어
  • 모든 장부를 쿼리합니다.

  • 프로젝트 구조



    이러한 명령을 실행하여 API를 만드는 데 필요한 필수 파일을 만듭니다.

    Note that the project structure can be much simpler than this, but my intention is to create a production ready structure that is easy to maintain and extend the code base in future.



    폴더를 만들어 보겠습니다.

    mkdir -p cmd pkg/books pkg/common/db  pkg/common/models
    


    몇 가지 파일을 추가해 보겠습니다.

    touch pkg/books/add_book.go pkg/books/controller.go pkg/books/delete_book.go pkg/books/get_book.go pkg/books/get_books.go pkg/books/update_book.go pkg/common/db/db.go  pkg/common/models/book.go
    


    최종 프로젝트 구조는 다음과 같아야 합니다.


    패키지 설치



    필요한 패키지를 설치하자.

    go get github.com/gin-gonic/gin
    go get gorm.io/gorm
    go get gorm.io/driver/postgres
    



    책 모델



    여기에서 Book 모델을 생성해 보겠습니다.
    pkg/common/models/book.go에 코드를 추가해 보겠습니다.

    package models
    
    import "gorm.io/gorm"
    
    type Book struct {
        gorm.Model
        Title       string `json:"title"`
        Author      string `json:"author"`
        Description string `json:"description"`
    }
    
    


    gorm.model will add properties such as ID, CreatedAt, UpdatedAt and DeletedAt for us out of the box.




    데이터베이스 초기화



    이제 Book Model이 완료되었으므로 GORM을 구성하고 방금 생성한 스키마를 자동 마이그레이션해야 합니다. 이 AutoMigrate 기능은 이 애플리케이션을 실행하자마자 데이터베이스에 books 테이블을 생성합니다.
    /pkg/common/db/db.go에 코드를 추가하자

    package db
    
    import (
        "log"
    
        "github.com/<YOUR-USERNAME>/go-gin-postgresql-api/pkg/common/models"
        "gorm.io/driver/postgres"
        "gorm.io/gorm"
    )
    
    func Init(url string) *gorm.DB {
        db, err := gorm.Open(postgres.Open(url), &gorm.Config{})
    
        if err != nil {
            log.Fatalln(err)
        }
    
        db.AutoMigrate(&models.Book{})
    
        return db
    }
    
    



    도서 처리기



    Book API에 일부 핸들러를 추가해 보겠습니다.

    제어 장치



    책 핸들러/라우트는 소위 Pointer receivers 을 기반으로 하므로 해당 구조체를 정의합니다.

    이 구조체는 나중에 데이터베이스 정보를 받을 것이므로 책 처리기/경로를 호출할 때마다 GROM에 액세스할 수 있습니다.

    나중에 이 파일을 다시 한 번 변경할 것입니다.
    pkg/books/controller.go에 코드를 추가해 보겠습니다.

    
    package books
    
    import (
        "gorm.io/gorm"
    )
    
    type handler struct {
        DB *gorm.DB
    }
    



    책 처리기 추가



    여기에서 요청 본문을 가져오고 새 책 변수를 선언하고 요청 본문을 이 책 변수와 병합하고 새 데이터베이스 항목을 만듭니다. 그런 다음 책 정보로 응답을 작성합니다.

    가져온 후 요청 본문의 구조체를 더럽힙니다. AddBook 함수에서 사용되는 포인터 리시버(h 핸들러)를 볼 수 있습니다. 데이터베이스에 액세스하기 위해 h(핸들러)를 사용하고 있습니다.
    pkg/books/add_book.go에 코드를 추가해 보겠습니다.

    package books
    
    import (
        "net/http"
    
        "github.com/<YOUR-USERNAME>/go-gin-postgresql-api/pkg/common/models"
        "github.com/gin-gonic/gin"
    )
    
    type AddBookRequestBody struct {
        Title       string `json:"title"`
        Author      string `json:"author"`
        Description string `json:"description"`
    }
    
    func (h handler) AddBook(ctx *gin.Context) {
        body := AddBookRequestBody{}
    
        if err := ctx.BindJSON(&body); err != nil {
            ctx.AbortWithError(http.StatusBadRequest, err)
            return
        }
    
        var book models.Book
    
        book.Title = body.Title
        book.Author = body.Author
        book.Description = body.Description
    
        if result := h.DB.Create(&book); result.Error != nil {
            ctx.AbortWithError(http.StatusNotFound, result.Error)
            return
        }
    
        ctx.JSON(http.StatusCreated, &book)
    }
    
    



    도서 핸들러 가져오기



    이 경로에서 데이터베이스의 모든 책을 반환합니다. 이것은 현재 매우 빠르게 작동하지만 처리할 더 큰 데이터가 있는 즉시 페이지 매김 접근 방식을 사용하는 것이 좋습니다.
    pkg/books/get_books.go에 코드를 추가해 보겠습니다.

    package books
    
    import (
        "net/http"
    
        "github.com/<YOUR-USERNAME>/go-gin-postgresql-api/pkg/common/models"
        "github.com/gin-gonic/gin"
    )
    
    func (h handler) GetBooks(ctx *gin.Context) {
        var books []models.Book
    
        if result := h.DB.Find(&books); result.Error != nil {
            ctx.AbortWithError(http.StatusNotFound, result.Error)
            return
        }
    
        ctx.JSON(http.StatusOK, &books)
    }
    
    



    책 처리기 가져오기



    여기에서는 매개변수에서 얻은 ID를 기반으로 1개의 책으로만 응답합니다.
    pkg/books/get_book.go에 코드를 추가해 보겠습니다.

    package books
    
    import (
        "net/http"
    
        "github.com/<YOUR-USERNAME>/go-gin-postgresql-api/pkg/common/models"
        "github.com/gin-gonic/gin"
    )
    
    func (h handler) GetBook(ctx *gin.Context) {
        id := ctx.Param("id")
    
        var book models.Book
    
        if result := h.DB.First(&book, id); result.Error != nil {
            ctx.AbortWithError(http.StatusNotFound, result.Error)
            return
        }
    
        ctx.JSON(http.StatusOK, &book)
    }
    
    



    책 처리기 업데이트



    책을 추가하면 생성된 책을 업데이트하는 옵션도 있어야 합니다. 이 경로는 이전에 코딩한 AddBook 경로와 유사합니다.
    pkg/books/update_book.go에 코드를 추가해 보겠습니다.

    package books
    
    import (
        "net/http"
    
        "github.com/<YOUR-USERNAME>/go-gin-postgresql-api/pkg/common/models"
        "github.com/gin-gonic/gin"
    )
    
    type UpdateBookRequestBody struct {
        Title       string `json:"title"`
        Author      string `json:"author"`
        Description string `json:"description"`
    }
    
    func (h handler) UpdateBook(ctx *gin.Context) {
        id := ctx.Param("id")
        body := UpdateBookRequestBody{}
    
        if err := ctx.BindJSON(&body); err != nil {
            ctx.AbortWithError(http.StatusBadRequest, err)
            return
        }
    
        var book models.Book
    
        if result := h.DB.First(&book, id); result.Error != nil {
            ctx.AbortWithError(http.StatusNotFound, result.Error)
            return
        }
    
        book.Title = body.Title
        book.Author = body.Author
        book.Description = body.Description
    
        h.DB.Save(&book)
    
        ctx.JSON(http.StatusOK, &book)
    }
    
    



    책 처리기 삭제



    이것이 이 기사의 마지막 경로입니다. 여기서는 ID를 기준으로 책을 삭제하지만 데이터베이스 내에 원하는 항목이 있는 경우에만 삭제합니다. HTTP 상태 코드로만 응답합니다.
    pkg/books/delete_book.go에 코드를 추가해 보겠습니다.

    package books
    
    import (
        "net/http"
    
        "github.com/<YOUR-USERNAME>/go-gin-postgresql-api/pkg/common/models"
        "github.com/gin-gonic/gin"
    )
    
    func (h handler) DeleteBook(ctx *gin.Context) {
        id := ctx.Param("id")
    
        var book models.Book
    
        if result := h.DB.First(&book, id); result.Error != nil {
            ctx.AbortWithError(http.StatusNotFound, result.Error)
            return
        }
    
        h.DB.Delete(&book)
    
        ctx.Status(http.StatusOK)
    }
    
    



    컨트롤러(다시)



    경로가 완료되었습니다. 이제 컨트롤러 파일을 다시 한 번 수정해야 합니다. 이번에는 RegisterRoutes라는 함수를 만듭니다. 함수가 무엇을 하는지 스스로 설명할 수 있습니다. 맞습니까?

    리시버 포인터를 기억하십니까? 여기에서 경로/핸들러에 대한 수신자 포인터를 얻습니다.

    컨트롤러 코드를 이것으로 업데이트하고,

    package books
    
    import (
        "github.com/gin-gonic/gin"
        "gorm.io/gorm"
    )
    
    type handler struct {
        DB *gorm.DB
    }
    
    func RegisterRoutes(router *gin.Engine, db *gorm.DB) {
        h := &handler{
            DB: db,
        }
    
        routes := router.Group("/books")
        routes.POST("/", h.AddBook)
        routes.GET("/", h.GetBooks)
        routes.GET("/:id", h.GetBook)
        routes.PUT("/:id", h.UpdateBook)
        routes.DELETE("/:id", h.DeleteBook)
    }
    
    



    메인 파일



    If you are following from , you already have viper initialised to handle our environment variables



    우리는 여기서 더 많은 일을 할 것입니다.
  • GORM을 기반으로 데이터베이스 초기화
  • Books 라우터 연결
  • 애플리케이션 시작 중

  • 또한 튜토리얼에서 이 파일을 변경할 것입니다.
    /cmd/main.go에 코드를 추가해 보겠습니다.

    package main
    
    import (
        "github.com/DevNiklesh/go-gin-postgresql-api/pkg/books"
        "github.com/DevNiklesh/go-gin-postgresql-api/pkg/common/db"
        "github.com/gin-gonic/gin"
        "github.com/spf13/viper"
    )
    
    func main() {
        viper.SetConfigFile("./pkg/common/envs/.env")
        viper.ReadInConfig()
    
        port := viper.Get("PORT").(string)
        dbUrl := viper.Get("DB_URL").(string)
    
        router := gin.Default()
        dbHandler := db.Init(dbUrl)
    
        books.RegisterRoutes(router, dbHandler)
    
        router.GET("/", func(ctx *gin.Context) {
            ctx.JSON(200, gin.H{
                "port":  port,
                "dbUrl": dbUrl,
            })
        })
    
        router.Run(port)
    }
    
    


    이제 코드를 실행해 보겠습니다.

    make server
    
    (OR)
    
    go run cmd/main
    




    지금 API를 테스트해보세요!

    이제 이를 모든 마이크로 서비스에 사용할 수 있으며 훨씬 쉽게 유지 관리할 수 있습니다.

    다음 자습서에서는 Golang을 사용하여 CRON 작업을 실행하는 방법을 살펴보겠습니다. 따라서 알림을 받으려면 여기와 안으로 나를 팔로우하십시오.

    이 시리즈가 마음에 드신다면 좋아요와 공유 부탁드립니다. 매우 감사! 감사.

    좋은 웹페이지 즐겨찾기