Postgres-Fehler in der API-Antwort zurückgeben
Ich habe zwei einfache API-Methoden in meinem Code. Methode mit Endpoind /api/user/create
erstellt Benutzer. Feld username
ist 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, user
mir 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
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
}
}
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.