API 응답에 postgres 오류 반환

Dec 24 2020

내 코드에는 두 가지 간단한 API 메서드가 있습니다. endpoind /api/user/create가있는 메소드는 사용자를 생성합니다. 필드 username는 고유합니다. 데이터베이스에 이미있는 동일한 사용자 이름으로 사용자를 만들려고 할 때 콘솔에 오류가 있습니다.

(/home/andrej/go/src/go_contacts/models/users.go:19) 
[2020-12-23 22:03:10]  pq: duplicate key value violates unique constraint "users_username_key"

사용자에 대한 응답으로이 오류를 표시하거나 어떻게 든 내 코드에서 오류 유형을 식별하여 사용자에게 다른 오류 메시지를 표시하고 싶습니다. 오류가 발생하면 userid = 0을 반환 한다는 것을 알고 있습니다. 그러나 그것은 사용자에게 좋은 메시지처럼 보이지 않습니다.

main.go

package main

import (
    "fmt"
    "go_contacts/controllers"
    "net/http"
    "os"

    "github.com/gorilla/mux"
    "github.com/joho/godotenv"
)

func main() {
    godotenv.Load(".env")


    router := mux.NewRouter()
    router.HandleFunc("/", controllers.ReturnHello).Methods("GET")
    router.HandleFunc("/api/user/create", controllers.CreateUser).Methods("POST")

    port := os.Getenv("PORT")
    if port == "" {
        port = "8000"
    }

    err := http.ListenAndServe(":"+port, router)
    if err != nil {
        fmt.Print(err)
    }
}

models.go 사용자 구조체 사용 :

package models

import (
    u "go_contacts/utils"

    "github.com/jinzhu/gorm"
)

// User base model
type User struct {
    gorm.Model
    Username string `json:"username" gorm:"unique"`
    Password string `json:"password"`
    Email    string `json:"email"`
}

// Create new user
func (user *User) Create() map[string]interface{} {
    GetDB().Create(user)

    if user.ID <= 0 {
        return u.Message(false, "Failed to create user, connection error.")
    }

    response := u.Message(true, "Account has been created")
    response["user"] = user
    return response
}

답변

1 AlekseySpirin Dec 24 2020 at 17:04

pq v1.5.2 및 gorm v1.9.12의 경우

먼저 create 메서드 호출이 오류를 반환하는지 여부를 식별해야합니다. 그렇게

err := GetDB().Create(user).Error
if err != nil {
    // code to handle error
}

그런 다음 pq 패키지에는 postgres 서버 오류에 매핑되는 특수 유형이 있습니다. 여기에는 오류 심각도, 오류와 관련된 코드, 테이블 등을 식별하는 데 도움이되는 필드가 포함되어 있습니다.

psql 필드 식별자의 전체 목록은 여기에서 찾을 수 있습니다.

오류 및 알림 메시지 필드

https://www.postgresql.org/docs/current/protocol-error-fields.html

옵션으로 문제를 해결하려면 필드를 사용할 수 있습니다.

Code

오류 코드의 문자열 유형 표현입니다. 하지만 먼저 오류를 캐스트하고 유형 캐스트가 성공했는지 확인해야합니다. 그렇게

err := GetDB().Create(user).Error
if err != nil {
    pqErr, ok := err.(pq.Error)
    if !ok {
        log.Fatal(err)
    }

    // code to handle specific error code
}

오류 코드 목록은 공식 postgresql 문서에서 모두 찾을 수 있습니다. https://www.postgresql.org/docs/9.3/errcodes-appendix.html

그리고 pq 라이브러리의 경우 github.com/lib/pq/error.go의 오류에 대한 실제 go pq 특정 매핑

마지막으로 오류를 코드에 의해 중복으로 처리 할 수 ​​있습니다.

err := GetDB().Create(user).Error
if err != nil {
    pqErr, ok := err.(pq.Error)
    if !ok {
        log.Fatal(err)
    }

    // note that type casting here is redundant and used for showing specific 
    // string type from pq library
    if pqErr.Code == pq.ErrorCode("23505") { // 23505 is unique_violation error code for psql
        // now you can create error and write it to a message to return it for 
        // a client
    }
}
1 Brits Dec 24 2020 at 02:59

의견에 따라 gorm 은 다음과 같이 레코드 생성 기능 에서 데이터베이스 오류에 대한 액세스를 제공 합니다.

result := GetDB().Create(user)
if result.Error != nil {
   // Do something with the error
}

오류 문자열을 확인하면 응용 프로그램 데이터베이스가 특정화 될 수 있습니다 (하지만 문제가되지 않을 수 있음). 이 질문에 대한 답변 은 추가 지원을 제공 할 수 있습니다.