Introduction
Dans le développement d'applications web, la validation des champs d'entrée est une étape essentielle pour garantir la sécurité et l'intégrité des données. Au lieu d'utiliser des expressions régulières pour chaque champ, la bibliothèque validator offre une solution plus élégente et efficace.
Installation
Pour commencer, installez la bibliothèque validator :
go get github.com/go-playground/validator/v10
Dans votre code, importez le package :
import "github.com/go-playground/validator/v10"
Fonctionnalités principales
La bibliothèque validator propose de nombreuses fonctionnalités de validation :
Symboles spéciaux dans les tags
- Virgule (
,) : Sépare plusieurs tags de validation (sans espaces) - Tiret (
-) : Ignore la validation du champ - Barre vertiacle (
|) : Plusieurs tags où l'un suffit pour valider required: Champ obligatoireomitempty: Ignore le champ s'il n'est pas défini
Validations de plage
Pour les nombres, les chaînes, les tranches et les maps :
lte: Inférieur ou égalgte: Supérieur ou égallt: Strictement inférieurgt: Strictement supérieurlen: Longueur exactemax: Valeur maximalemin: Valeur minimalene: Différent deoneof: Doit être l'une des valeurs spécifiées
Exemple :
type Utilisateur struct {
Nom string `validate:"min=2,max=50"`
Age uint8 `validate:"gte=18,lte=120"`
}
Validations de chaînes
contains: Contient la sous-chaîne spécifiéeexcludes: Ne contient pas la sous-chaîne spécifiéestartswith: Commence par la sous-chaîne spécifiéeendswith: Se termine par la sous-chaîne spécifiée
Validations de champs
eqfield: Champ égal à un autre champ de la même structurenefield: Champ différent d'un autre champgtefield: Champ supérieur ou égal à un autre champltefield: Champ inférieur ou égal à un autre champ
Validations réseau
ip: Adresse IP valideipv4: Adresse IPv4 valideipv6: Adresse IPv6 valideuri: URI valideurl: URL valide
Exemples pratiques
Exemple 1 : Validation d'une valeur simple
package main
import (
"fmt"
"github.com/go-playground/validator/v10"
)
func main() {
validateur := validator.New()
// Validation d'un email
email := "test@example.com"
err := validateur.Var(email, "required,email")
if err != nil {
fmt.Printf("Email invalide: %v\n", err)
} else {
fmt.Println("Email valide")
}
// Validation d'un nombre
nombre := 25
err = validateur.Var(nombre, "gt=0,lt=100")
if err != nil {
fmt.Printf("Nombre invalide: %v\n", err)
} else {
fmt.Println("Nombre valide")
}
}
Exemple 2 : Validation d'une structure
package main
import (
"fmt"
"github.com/go-playground/validator/v10"
)
type Profil struct {
Prenom string `validate:"required"`
Nom string `validate:"required"`
Age uint8 `validate:"gte=18,lte=120"`
Courriel string `validate:"required,email"`
Adresses []Adresse `validate:"required,dive,required"`
}
type Adresse struct {
Rue string `validate:"required"`
Ville string `validate:"required"`
Pays string `validate:"required"`
CodePostal string `validate:"required"`
}
func main() {
profil := &Profil{
Prenom: "Jean",
Nom: "Dupont",
Age: 30,
Courriel: "jean.dupont@example.com",
Adresses: []Adresse{
{
Rue: "123 Rue Principale",
Ville: "Paris",
Pays: "France",
CodePostal: "75001",
},
},
}
validateur := validator.New()
err := validateur.Struct(profil)
if err != nil {
fmt.Println("Erreurs de validation:")
for _, erreur := range err.(validator.ValidationErrors) {
fmt.Printf("- Champ: %s, Erreur: %s\n", erreur.Field(), erreur.Tag())
}
} else {
fmt.Println("Structure valide")
}
}
Exemple 3 : Validation de tranches et maps
package main
import (
"fmt"
"github.com/go-playground/validator/v10"
)
func main() {
validateur := validator.New()
// Validation d'une tranche
noms := []string{"Alice", "Bob", "Charlie"}
err := validateur.Var(noms, "max=5,dive,min=3")
if err != nil {
fmt.Printf("Erreurs dans la tranche: %v\n", err)
} else {
fmt.Println("Tranche valide")
}
// Validation d'une map
preferences := map[string]string{
"couleur": "bleu",
"taille": "moyen",
}
err = validateur.Var(preferences, "gte=2,dive,keys,eq=couleur|eq=taille,endkeys,required")
if err != nil {
fmt.Printf("Erreurs dans la map: %v\n", err)
} else {
fmt.Println("Map valide")
}
}
Exemple 4 : Validation personnalisée
package main
import (
"fmt"
"github.com/go-playground/validator/v10"
)
type Produit struct {
Nom string `validate:"required,nomValide"`
Prix float64 `validate:"gt=0"`
Categorie string `validate:"required"`
}
func main() {
validateur := validator.New()
// Enregistrement d'une validation personnalisée
err := validateur.RegisterValidation("nomValide", func(fl validator.FieldLevel) bool {
nom := fl.Field().String()
return len(nom) >= 3 && !containsNumber(nom)
})
if err != nil {
fmt.Printf("Erreur lors de l'enregistrement: %v\n", err)
return
}
produit := &Produit{
Nom: "Produit123",
Prix: 19.99,
Categorie: "Électronique",
}
err = validateur.Struct(produit)
if err != nil {
fmt.Printf("Produit invalide: %v\n", err)
} else {
fmt.Println("Produit valide")
}
}
func containsNumber(s string) bool {
for _, char := range s {
if char >= '0' && char <= '9' {
return true
}
}
return false
}
Exemple 5 : Validation entre champs
package main
import (
"fmt"
"github.com/go-playground/validator/v10"
)
type Inscription struct {
NomUtilisateur string `validate:"min=4,max=20"`
MotDePasse string `validate:"min=8"`
Confirmation string `validate:"eqfield=MotDePasse"`
Email string `validate:"email"`
}
func main() {
validateur := validator.New()
// Cas 1 : Mots de passe différents
utilisateur1 := Inscription{
NomUtilisateur: "jean",
MotDePasse: "motdepasse123",
Confirmation: "motdepasse456",
Email: "jean@example.com",
}
err := validateur.Struct(utilisateur1)
if err != nil {
fmt.Printf("Inscription 1 invalide: %v\n", err)
}
// Cas 2 : Mots de passe identiques
utilisateur2 := Inscription{
NomUtilisateur: "jean",
MotDePasse: "motdepasse123",
Confirmation: "motdepasse123",
Email: "jean@example.com",
}
err = validateur.Struct(utilisateur2)
if err != nil {
fmt.Printf("Inscription 2 invalide: %v\n", err)
} else {
fmt.Println("Inscription 2 valide")
}
}
Exemple 6 : Traduction des messages d'erreur
package main
import (
"fmt"
"strings"
"github.com/go-playground/locales/fr"
ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
frtrans "github.com/go-playground/validator/v10/translations/fr"
)
type Etudiant struct {
Nom string `validate:"required"`
Email string `validate:"email"`
Age int `validate:"min=16,max=30"`
}
func main() {
// Configuration du traducteur
fr := fr.New()
uni := ut.New(fr)
trans, _ := uni.GetTranslator("fr")
validateur := validator.New()
frtrans.RegisterDefaultTranslations(validateur, trans)
etudiant := Etudiant{
Nom: "Marie",
Email: "email invalide",
Age: 35,
}
err := validateur.Struct(etudiant)
if err != nil {
erreurs := err.(validator.ValidationErrors)
messages := nettoyerNomStructure(erreurs.Translate(trans))
fmt.Println("Erreurs de validation:")
for champ, message := range messages {
fmt.Printf("- %s: %s\n", champ, message)
}
}
}
func nettoyerNomStructure(erreurs map[string]string) map[string]string {
result := make(map[string]string)
for champ, message := range erreurs {
result[champ[strings.Index(champ, ".")+1:]] = message
}
return result
}
Conclusion
La bibliothèque validator offre une solution puissante et flexible pour la validation des données dans les applications Go. Avec ses nombreuses fonctionnalités intégrées et la possibilité de créer des validations personnalisées, elle simplifie considérablement le processus de validation des données.