Postgres-Fehler in der API-Antwort zurückgeben

Dec 24 2020

Ich habe zwei einfache API-Methoden in meinem Code. Methode mit Endpoind /api/user/createerstellt Benutzer. Feld usernameist einzigartig. Wenn ich versuche, einen Benutzer mit demselben Benutzernamen zu erstellen, der bereits in der Datenbank vorhanden ist, ist in der Konsole ein Fehler aufgetreten:

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

Ich möchte diesen Fehler als Antwort auf den Benutzer anzeigen oder irgendwie den Fehlertyp in meinem Code identifizieren, um verschiedene Fehlermeldungen für den Benutzer anzuzeigen. Ich weiß nur, dass wenn ich einen Fehler habe, usermir id = 0 zurückgegeben wird. Aber es scheint keine gute Nachricht für den Benutzer zu sein.

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 mit Benutzerstruktur:

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
}

Antworten

1 AlekseySpirin Dec 24 2020 at 17:04

Wie für pq v1.5.2 und gorm v1.9.12

Zunächst müssen Sie feststellen, ob der Aufruf der Methode create einen Fehler zurückgibt oder nicht. Wie so

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

Dann hat das pq-Paket einen speziellen Typ, der dem Postgres-Serverfehler zugeordnet ist. Es enthält Felder, mit denen Sie die Schwere des Fehlers, den Code, die Tabelle, die sich auf den Fehler beziehen, usw. identifizieren können.

Eine vollständige Liste der Bezeichner für psql-Felder finden Sie hier in

Fehler- und Hinweismeldungsfelder

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

Um Ihr Problem als Option zu beheben, können wir das Feld verwenden

Code

Dies ist eine Zeichenfolgentypdarstellung des Fehlercodes. Aber zuerst müssen wir einen Fehler umwandeln und überprüfen, ob die Typumwandlung erfolgreich war. Wie so

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

    // code to handle specific error code
}

Eine Liste der Fehlercodes finden Sie in den offiziellen Postgresql-Dokumenten https://www.postgresql.org/docs/9.3/errcodes-appendix.html

Und tatsächliche go pq-spezifische Zuordnungen zu dem Fehler in github.com/lib/pq/error.go wie für die pq-Bibliothek

Und schließlich können wir Fehler als Duplikat durch Code behandeln

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

Gemäß den Kommentaren bietet gorm den Zugriff auf Datenbankfehler über die Funktion " Datensatz erstellen" wie folgt:

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

Bitte beachten Sie, dass das Überprüfen der Fehlerzeichenfolge wahrscheinlich Ihre Anwendungsdatenbank spezifisch macht (dies ist jedoch möglicherweise kein Problem für Sie). Die Antworten auf diese Frage können weitere Unterstützung bieten.