Trả lại lỗi postgres trong phản hồi api

Dec 24 2020

Tôi có hai phương thức api đơn giản trong mã của mình. Phương thức với endpoind /api/user/createtạo người dùng. Trường usernamelà duy nhất. Khi tôi cố gắng tạo người dùng có cùng tên người dùng đã tồn tại trong cơ sở dữ liệu, tôi gặp lỗi trong bảng điều khiển:

(/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"

Tôi muốn hiển thị lỗi này để phản hồi cho người dùng hoặc bằng cách nào đó xác định loại lỗi trong mã của tôi, để hiển thị các thông báo lỗi khác nhau cho người dùng. Tôi chỉ biết rằng nếu tôi gặp lỗi, hãy usertrả về cho tôi id = 0. Nhưng nó có vẻ không phải là một thông điệp tốt cho người dùng.

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 với cấu trúc người dùng:

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
}

Trả lời

1 AlekseySpirin Dec 24 2020 at 17:04

Đối với pq v1.5.2 và gorm v1.9.12

Trước tiên, bạn cần xác định xem liệu cuộc gọi phương thức tạo có trả lại lỗi hay không. Như vậy

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

Sau đó, gói pq có loại đặc biệt ánh xạ đến lỗi máy chủ postgres. Nó chứa các trường có thể giúp bạn xác định mức độ nghiêm trọng của lỗi, đó là mã, bảng liên quan đến lỗi, v.v.

Danh sách đầy đủ các định danh trường psql có thể được tìm thấy tại đây trong

Các trường Thông báo Lỗi và Thông báo

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

Để giải quyết vấn đề của bạn dưới dạng một tùy chọn, chúng tôi có thể sử dụng trường

Code

Đó là một dạng chuỗi biểu diễn mã lỗi. Nhưng trước tiên, chúng ta cần ép kiểu lỗi và kiểm tra kiểu ép thành công. Như vậy

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

    // code to handle specific error code
}

Danh sách mã lỗi có thể được tìm thấy cả trong tài liệu postgresql chính thức https://www.postgresql.org/docs/9.3/errcodes-appendix.html

Và thực tế ánh xạ pq cụ thể đến lỗi trong github.com/lib/pq/error.go như đối với thư viện pq

Và cuối cùng, chúng tôi có thể xử lý lỗi là trùng lặp theo mã

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

Theo các nhận xét, gorm cung cấp quyền truy cập vào các lỗi cơ sở dữ liệu từ chức năng Tạo bản ghi như sau:

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

Xin lưu ý rằng việc kiểm tra chuỗi lỗi có thể làm cho cơ sở dữ liệu ứng dụng của bạn trở nên cụ thể (nhưng đây có thể không phải là vấn đề đối với bạn). Câu trả lời cho câu hỏi này có thể cung cấp hỗ trợ thêm.