API yanıtında postgres hatalarını döndür

Dec 24 2020

Kodumda iki basit api yöntemim var. Uç noktalı yöntem /api/user/createkullanıcı oluşturur. Alan usernamebenzersizdir. Veritabanında zaten mevcut olan aynı kullanıcı adına sahip bir kullanıcı oluşturmaya çalışırken, konsolda bir hata alıyorum:

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

Kullanıcıya farklı hata mesajları göstermek için bu hatayı kullanıcıya yanıt olarak göstermek veya bir şekilde kodumdaki hata türünü tanımlamak istiyorum. Sadece hata useralırsam bana id = 0 döndürdüğünü biliyorum . Ancak kullanıcı için iyi bir mesaj gibi görünmüyor.

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 kullanıcı yapısı ile:

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
}

Yanıtlar

1 AlekseySpirin Dec 24 2020 at 17:04

Pq v1.5.2 ve gorm v1.9.12 ile ilgili olarak

İlk olarak, yöntem çağrısı oluşturmanın hata döndürüp döndürmediğini belirlemeniz gerekir. Öyle gibi

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

Daha sonra pq paketi, postgres sunucu hatasıyla eşleşen özel bir türe sahiptir. Hatanın önem derecesini, kodunu, hatayla ilgili tablo vb. Tanımlamanıza yardımcı olabilecek alanlar içerir.

Psql alan tanımlayıcılarının tam listesi şurada bulunabilir:

Hata ve Uyarı Mesajı Alanları

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

Sorununuzu çözmek için bir seçenek olarak alanı kullanabiliriz

Code

Hata kodunun dize türü gösterimidir. Ama önce bir hata yapmalıyız ve tip atımının başarılı olup olmadığını kontrol etmeliyiz. Öyle gibi

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

    // code to handle specific error code
}

Hata kodlarının listesi hem resmi postgresql belgelerinde bulunabilir. https://www.postgresql.org/docs/9.3/errcodes-appendix.html

Ve pq kitaplığında olduğu gibi github.com/lib/pq/error.go'daki hataya gerçek go pq'ye özgü eşlemeler

Ve son olarak, hatayı koda göre yinelenen olarak ele alabiliriz

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

Yorumlar başı olarak gorm erişim sağlar veritabanı hataları gelen oluşturun rekor şöyle fonksiyonu:

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

Lütfen hata dizesini kontrol etmenin uygulama veritabanınızı özel hale getireceğini unutmayın (ancak bu sizin için bir sorun olmayabilir). Bu sorunun cevapları daha fazla yardım sağlayabilir.