GORM을 사용하여 PostgreSQL에 연결

36966 단어 dockergopostgres
본고는 마지막 부분의 기초 위에서 간단한 것을 세웠다.이제 API를 진정한 데이터베이스에 연결합시다!여기서는 PostgreSQL과GORM를 사용하여 이 점을 실현할 것입니다.
본문의 모든 코드는 사용 가능here
만약 네가 원한다면, 나는 또 동영상을 하나 만들었다!

설치 프로그램


코드를 사용하기 전에,postgres 데이터베이스를 개발해야 합니다.가장 간단한 방법은 사용Docker이다.그러니까 확실하게 docker installed.
이제 docker-compose.yml 파일을 정의하면 데이터베이스 사용을 더욱 쉽게 할 수 있습니다.
version: "3.8"

services:
  database:
    container_name: database
    image: postgres:12.8
    restart: always
    environment:
      - POSTGRES_USER=pg
      - POSTGRES_PASSWORD=pass
      - POSTGRES_DB=crud
    ports:
      - 5432:5432
    volumes:
      - db:/var/lib/postgresql/data 

volumes:
  db:
Postgres 컨테이너를 시작하겠습니다!
$ docker compose up -d
데이터베이스에 연결
일단 데이터베이스가 실행되면, 우리는 어떠한 데이터베이스 관리 도구 (예: pgAdmin 를 통해 그것에 연결할 수 있다.여기서 TablePlus를 사용하고 PostgreSQL 형식의 연결을 만들 것입니다.
docker-compose.yml와 같은 모든 세부 사항을 추가합니다.그래서 저희 사용자는pg, 비밀번호는pass, 데이터베이스는crud입니다.다음에 테스트를 클릭하여 데이터베이스에 접근할 수 있는지 확인할 수 있습니다.그런 다음 접속 을 클릭합니다.

이제 우리는 우리의 책상을 볼 수 있을 것이다.

GORM 설정


GORM과 Postgres 드라이버를 설치합니다.
$ go get -u gorm.io/gorm
$ go get -u gorm.io/driver/postgres
모델 업데이트pkg/models/book.go로 이동하여 구조 표지에서 IdprimaryKey로 성명하겠습니다.
package models

type Book struct {
    Id     int    `json:"id" gorm:"primaryKey"`
    Title  string `json:"title"`
    Author string `json:"author"`
    Desc   string `json:"desc"`
}
데이터베이스 패키지
이제 dbpkg/db/db.go 패키지를 만듭니다.Init 함수에서 우리는 dbURLPostgres 데이터베이스에 연결하기만 하면 된다.
그 밖에 우리는 db.AutoMigrate 이동 모델을 사용할 수 있다.
참고: Dell은 dbURL를 환경 변수로 저장할 수도 있지만 단순히 여기에만 추가할 수 있습니다.
package db

import (
    "log"

    "github.com/tutorials/go/crud/pkg/models"
    "gorm.io/driver/postgres"
    "gorm.io/gorm"
)

func Init() *gorm.DB {
    dbURL := "postgres://pg:pass@localhost:5432/crud"

    db, err := gorm.Open(postgres.Open(dbURL), &gorm.Config{})

    if err != nil {
        log.Fatalln(err)
    }

    db.AutoMigrate(&models.Book{})

    return db
}
의존 주입
현재 우리는db 설정을 가지고 있으니, 처리 프로그램에서 그것을 어떻게 사용하는지 생각해 봅시다.우리는 모든 처리 프로그램에서 Init을 호출할 수 없다. 왜냐하면 이것은 대량의 데이터베이스 연결을 만들기 때문이다.따라서 우리는 그것을 한 번 초기화하여 처리 프로그램에 전달할 것이다.이를 위해 우리는 의존 주입을 이용할 수 있다.여기서 handlerstruct를 성명합시다.
package handlers

import "gorm.io/gorm"

type handler struct {
    DB *gorm.DB
}

func New(db *gorm.DB) handler {
    return handler{db}
}
이제 처리 프로그램을 수신자 함수로 업데이트합니다.pkg/handlers/GetAllBooks.go
func (h handler) GetAllBooks(w http.ResponseWriter, r *http.Request) {}
pkg/handlers/GetBook.go
func (h handler) GetBook(w http.ResponseWriter, r *http.Request) {}
pkg/handlers/AddBook.go
func (h handler) AddBook(w http.ResponseWriter, r *http.Request) {}
pkg/handlers/UpdateBook.go
func (h handler) UpdateBook(w http.ResponseWriter, r *http.Request) {}
pkg/handlers/DeleteBook.go
func (h handler) DeleteBook(w http.ResponseWriter, r *http.Request) {}
업데이트 주
요컨대, 아래와 같이 데이터베이스와 처리 프로그램을 초기화합시다.
package main

import (
    "log"
    "net/http"

    "github.com/gorilla/mux"
    "github.com/tutorials/go/crud/pkg/db"
    "github.com/tutorials/go/crud/pkg/handlers"
)

func main() {
    DB := db.Init()
    h := handlers.New(DB)
    router := mux.NewRouter()

    router.HandleFunc("/books", h.GetAllBooks).Methods(http.MethodGet)
    router.HandleFunc("/books/{id}", h.GetBook).Methods(http.MethodGet)
    router.HandleFunc("/books", h.AddBook).Methods(http.MethodPost)
    router.HandleFunc("/books/{id}", h.UpdateBook).Methods(http.MethodPut)
    router.HandleFunc("/books/{id}", h.DeleteBook).Methods(http.MethodDelete)

    log.Println("API is running!")
    http.ListenAndServe(":4000", router)
}
이제 API를 실행하겠습니다.
$ go run cmd/main.go

프로세서 업데이트


이제 GORM 대신 아날로그 구현을 사용하여 프로세서를 업데이트합니다.
주소록
여기서 우리는 h.DB.Create를 사용하여 우리의 책을 만들 수 있다.
package handlers

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "log"
    "net/http"

    "github.com/tutorials/go/crud/pkg/models"
)

func (h handler) AddBook(w http.ResponseWriter, r *http.Request) {
    // Read to request body
    defer r.Body.Close()
    body, err := ioutil.ReadAll(r.Body)

    if err != nil {
        log.Fatalln(err)
    }

    var book models.Book
    json.Unmarshal(body, &book)

    // Append to the Books table
    if result := h.DB.Create(&book); result.Error != nil {
        fmt.Println(result.Error)
    }

    // Send a 201 created response
    w.Header().Add("Content-Type", "application/json")
    w.WriteHeader(http.StatusCreated)
    json.NewEncoder(w).Encode("Created")
}
우체부로 테스트한 후에 책 한 권을 쓰자.데이터베이스에 반영된 것을 검사합니다.

보아하니 우리는 새 책 한 권을 늘린 것 같다.

삭제본
여기서 우리는 먼저 h.DB.First로 이 책을 조회한 다음에 우리가 사용한 h.DB.Delete로 찾은 책을 간단하게 삭제할 수 있다.
package handlers

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

    "github.com/gorilla/mux"
    "github.com/tutorials/go/crud/pkg/models"
)

func (h handler) DeleteBook(w http.ResponseWriter, r *http.Request) {
    // Read the dynamic id parameter
    vars := mux.Vars(r)
    id, _ := strconv.Atoi(vars["id"])

    // Find the book by Id

    var book models.Book

    if result := h.DB.First(&book, id); result.Error != nil {
        fmt.Println(result.Error)
    }

    // Delete that book
    h.DB.Delete(&book)

    w.Header().Add("Content-Type", "application/json")
    w.WriteHeader(http.StatusOK)
    json.NewEncoder(w).Encode("Deleted")
}
우체부로 삭제 요청을 보내겠습니다.

만약 우리가 데이터베이스를 검사한다면 이 책이 삭제된 것을 발견할 수 있을 것이다.

모든 책 가져오기
이곳에서 우리는 간단하게 h.DB.Find로 모든 책을 얻을 수 있다.
package handlers

import (
    "encoding/json"
    "fmt"
    "net/http"

    "github.com/tutorials/go/crud/pkg/models"
)

func (h handler) GetAllBooks(w http.ResponseWriter, r *http.Request) {
    var books []models.Book

    if result := h.DB.Find(&books); result.Error != nil {
        fmt.Println(result.Error)
    }

    w.Header().Add("Content-Type", "application/json")
    w.WriteHeader(http.StatusOK)
    json.NewEncoder(w).Encode(books)
}


GetBook
여기에서, 우리는 h.DB.Find 요청 주체로부터의 책 id를 사용하여 id에 따라 책을 조회할 것입니다.
package handlers

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

    "github.com/gorilla/mux"
    "github.com/tutorials/go/crud/pkg/models"
)

func (h handler) GetBook(w http.ResponseWriter, r *http.Request) {
    // Read dynamic id parameter
    vars := mux.Vars(r)
    id, _ := strconv.Atoi(vars["id"])

    // Find book by Id
    var book models.Book

    if result := h.DB.First(&book, id); result.Error != nil {
        fmt.Println(result.Error)
    }

    w.Header().Add("Content-Type", "application/json")
    w.WriteHeader(http.StatusOK)
    json.NewEncoder(w).Encode(book)
}
우체부와 함께 해 봅시다.

갱신본
마지막으로, GetBook 프로세서와 유사한 책 by id를 먼저 찾고, 요청한 본문으로 필드를 업데이트할 것입니다.그리고 우리는 그것을 간단하게 보존할 수 있다.
package handlers

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
    "strconv"

    "github.com/gorilla/mux"
    "github.com/tutorials/go/crud/pkg/models"
)

func (h handler) UpdateBook(w http.ResponseWriter, r *http.Request) {
    // Read dynamic id parameter
    vars := mux.Vars(r)
    id, _ := strconv.Atoi(vars["id"])

    // Read request body
    defer r.Body.Close()
    body, err := ioutil.ReadAll(r.Body)

    if err != nil {
        log.Fatalln(err)
    }

    var updatedBook models.Book
    json.Unmarshal(body, &updatedBook)

    var book models.Book

    if result := h.DB.First(&book, id); result.Error != nil {
        fmt.Println(result.Error)
    }

    book.Title = updatedBook.Title
    book.Author = updatedBook.Author
    book.Desc = updatedBook.Desc

    h.DB.Save(&book)

    w.Header().Add("Content-Type", "application/json")
    w.WriteHeader(http.StatusOK)
    json.NewEncoder(w).Encode("Updated")
}
우체부에게 신속하게 요청을 하고, 우리의 books 표를 봅시다.

과연 이 책은 갱신되었다.

깨끗이 정리하다
마지막으로 삭제pkg/mocks하겠습니다. 저희 프로젝트 구조는 이렇습니다.
├── cmd
│   └── main.go
├── pkg
│    ├── handlers
│    │   ├── handler.go
│    │   ├── AddBook.go
│    │   ├── DeleteBook.go
│    │   ├── GetAllBooks.go
│    │   ├── GetBook.go
│    │   └── UpdateBook.go
│    ├── db
│    │   └── db.go
│    └── models
│        └── book.go
├── docker-compose.yml
├── go.sum
└── go.mod

다음 단계


그래서 드디어 CRUD API와 PostgreSQL을 연결했습니다!우리의 다음 단계는 테스트를 추가하고 재구성을 진행할 수 있습니다. 우리는 다음 부분에서 진행할 것입니다!
나는 이것이 도움이 되기를 바란다. 왜냐하면 만약 당신이 어떤 문제에 부딪히면 언제든지 연락하십시오.
좋은 하루 되세요!

좋은 웹페이지 즐겨찾기