ส่งคืนข้อผิดพลาด postgres ในการตอบสนอง api
ฉันมีวิธี 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"
ฉันต้องการแสดงข้อผิดพลาดนี้เพื่อตอบสนองต่อผู้ใช้หรือระบุประเภทข้อผิดพลาดในรหัสของฉันเพื่อแสดงข้อความแสดงข้อผิดพลาดที่แตกต่างกันสำหรับผู้ใช้ ฉันรู้เพียงว่าถ้าฉันมีข้อผิดพลาดuserจะส่งคืนฉัน id = 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
}
คำตอบ
สำหรับ pq v1.5.2 และ gorm v1.9.12
ขั้นแรกคุณต้องระบุว่าสร้างการเรียกใช้เมธอดส่งคืนข้อผิดพลาดหรือไม่ เช่นนั้น
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 สำหรับไลบรารี 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
}
}
ตามความคิดเห็นgormให้การเข้าถึงข้อผิดพลาดของฐานข้อมูลจากฟังก์ชันCreate recordดังต่อไปนี้:
result := GetDB().Create(user)
if result.Error != nil {
// Do something with the error
}
โปรดทราบว่าการตรวจสอบสตริงข้อผิดพลาดมีแนวโน้มที่จะทำให้ฐานข้อมูลแอปพลิเคชันของคุณมีความเฉพาะเจาะจง (แต่นี่อาจไม่ใช่ปัญหาสำหรับคุณ) คำตอบสำหรับคำถามนี้อาจให้ความช่วยเหลือเพิ่มเติม