Retourne des erreurs postgres dans la réponse de l'API
J'ai deux méthodes API simples dans mon code. La méthode avec endpoind /api/user/create
crée l'utilisateur. Le champ username
est unique. Lorsque j'essaie de créer un utilisateur avec le même nom d'utilisateur qui existe déjà dans la base de données, j'ai une erreur dans la console:
(/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"
Je veux afficher cette erreur en réponse à l'utilisateur, ou identifier en quelque sorte le type d'erreur dans mon code, pour afficher différents messages d'erreur pour l'utilisateur. Je sais seulement que si j'ai une erreur user
me renvoie id = 0. Mais cela ne semble pas être un bon message pour l'utilisateur.
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
avec la structure de l'utilisateur:
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
}
Réponses
Comme pour pq v1.5.2 et gorm v1.9.12
Tout d'abord, vous devez identifier si l'appel de méthode de création renvoie une erreur ou non. Ainsi
err := GetDB().Create(user).Error
if err != nil {
// code to handle error
}
Ensuite, le package pq a un type spécial qui correspond à une erreur de serveur postgres. Il contient des champs qui peuvent vous aider à identifier la gravité de l'erreur, son code, la table liée à l'erreur, etc.
La liste complète des identificateurs de champs psql peut être trouvée ici dans
Champs de message d'erreur et d'avis
https://www.postgresql.org/docs/current/protocol-error-fields.html
Pour résoudre votre problème en option, nous pouvons utiliser le champ
Code
Qui est une représentation de type chaîne du code d'erreur. Mais tout d'abord, nous devons convertir une erreur et vérifier que la conversion du type a réussi. Ainsi
err := GetDB().Create(user).Error
if err != nil {
pqErr, ok := err.(pq.Error)
if !ok {
log.Fatal(err)
}
// code to handle specific error code
}
La liste des codes d'erreur peut être trouvée à la fois dans la documentation officielle de PostgreSQL https://www.postgresql.org/docs/9.3/errcodes-appendix.html
Et les mappages spécifiques de go pq à l'erreur dans github.com/lib/pq/error.go comme pour la bibliothèque pq
Et enfin, nous pouvons gérer l'erreur comme une duplication par code
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
}
}
Selon les commentaires, gorm permet d'accéder aux erreurs de base de données à partir de la fonction Créer un enregistrement comme suit:
result := GetDB().Create(user)
if result.Error != nil {
// Do something with the error
}
Veuillez noter que la vérification de la chaîne d'erreur est susceptible de rendre votre base de données d'application spécifique (mais cela peut ne pas être un problème pour vous). Les réponses à cette question peuvent apporter une aide supplémentaire.