Skip to content

Commit 7fadddd

Browse files
committed
Init
0 parents  commit 7fadddd

File tree

5 files changed

+208
-0
lines changed

5 files changed

+208
-0
lines changed

go.mod

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module github.com/debug-ing/validation-go
2+
3+
go 1.22.3
4+
5+
require github.com/google/uuid v1.6.0

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
2+
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=

main.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/debug-ing/validation-go/pkg/validation"
7+
)
8+
9+
type UpdateIAMUserRequest struct {
10+
ID string `validate:"required,uuid"`
11+
Name string `validate:"required,minlength=10"`
12+
LName string `validate:"required,minlength=10"`
13+
Age int `validate:"required,numeric,minmax=18-100"`
14+
Nike string `validate:"required,between=1-10"`
15+
}
16+
17+
func main() {
18+
req := UpdateIAMUserRequest{
19+
ID: "d89cb260-36ff-4206-8979-6c1ce693ab28",
20+
Name: "ddsffddddd",
21+
LName: "ddsffddddd",
22+
Age: 29,
23+
Nike: "sdfkjdf",
24+
}
25+
//
26+
err := validation.ValidateStruct(req)
27+
if err != nil {
28+
fmt.Println("Validation error:", err)
29+
} else {
30+
fmt.Println("Validation passed")
31+
}
32+
}

pkg/validation/rules.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package validation
2+
3+
import (
4+
"errors"
5+
"strconv"
6+
"strings"
7+
8+
"github.com/google/uuid"
9+
)
10+
11+
func validateRequired(value string, errorMsg string) error {
12+
if value == "" {
13+
return errors.New(errorMsg)
14+
}
15+
return nil
16+
}
17+
18+
func validationIsUUID(value string, errorMsg string) error {
19+
_, err := uuid.Parse(value)
20+
if err != nil {
21+
return errors.New(errorMsg)
22+
}
23+
return nil
24+
}
25+
26+
func validateMinLength(value string, min int, errorMsg string) error {
27+
if len(value) < min {
28+
return errors.New(errorMsg)
29+
}
30+
return nil
31+
}
32+
func validateIsEmail(value string, errorMsg string) error {
33+
if !strings.Contains(value, "@") {
34+
return errors.New(errorMsg)
35+
}
36+
return nil
37+
}
38+
func validateIsNumber(value string, errorMsg string) error {
39+
if _, err := strconv.Atoi(value); err != nil {
40+
return errors.New(errorMsg)
41+
}
42+
return nil
43+
}
44+
45+
func validationBetween(value string, min, max int, errorMsg string) error {
46+
if len(value) < min || len(value) > max {
47+
return errors.New(errorMsg)
48+
}
49+
return nil
50+
}
51+
52+
func validationMinMaxNumber(value string, min, max int, errorMsg string) error {
53+
num, err := strconv.Atoi(value)
54+
if err != nil {
55+
return errors.New(errorMsg)
56+
}
57+
58+
if num < min || num > max {
59+
return errors.New(errorMsg)
60+
}
61+
return nil
62+
}

pkg/validation/validator.go

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package validation
2+
3+
import (
4+
"fmt"
5+
"reflect"
6+
"strconv"
7+
"strings"
8+
)
9+
10+
var validators = map[string]interface{}{
11+
"required": validateRequired,
12+
"minlength": validateMinLength,
13+
"uuid": validationIsUUID,
14+
"email": validateIsEmail,
15+
"numeric": validateIsNumber,
16+
"between": validationBetween,
17+
"minmax": validationMinMaxNumber,
18+
}
19+
20+
var data = map[string]map[string]string{
21+
"required": {
22+
"error_msg": "%s field is required.",
23+
},
24+
"minlength": {
25+
"error_msg": "%s must be at least %d characters long.",
26+
},
27+
"uuid": {
28+
"error_msg": "%s must be a valid UUID.",
29+
},
30+
"email": {
31+
"error_msg": "%s must be a valid email address.",
32+
},
33+
"numeric": {
34+
"error_msg": "%s must be a number.",
35+
},
36+
"between": {
37+
"error_msg": "%s must be between %d and %d characters long.",
38+
},
39+
"minmax": {
40+
"error_msg": "%s must be between %d and %d.",
41+
},
42+
}
43+
44+
func ValidateStruct(s interface{}) error {
45+
v := reflect.ValueOf(s)
46+
t := v.Type()
47+
for i := 0; i < t.NumField(); i++ {
48+
field := t.Field(i)
49+
value := v.Field(i)
50+
fieldName := field.Name
51+
validateTag := field.Tag.Get("validate")
52+
data := strings.Split(validateTag, ",")
53+
for _, d := range data {
54+
parts := strings.SplitN(d, "=", 2)
55+
tagName := parts[0]
56+
var tagParam string
57+
if len(parts) > 1 {
58+
tagParam = parts[1]
59+
}
60+
if validator, exists := validators[tagName]; exists {
61+
switch validator := validator.(type) {
62+
case func(string, string) error:
63+
errorMsg := getMessage(tagName, fieldName)
64+
if err := validator(fmt.Sprint(value), errorMsg); err != nil {
65+
return err
66+
}
67+
case func(string, int, string) error:
68+
if param, err := strconv.Atoi(tagParam); err == nil {
69+
errorMsg := getMessage(tagName, fieldName, param)
70+
if err := validator(value.String(), param, errorMsg); err != nil {
71+
return err
72+
}
73+
} else {
74+
return fmt.Errorf("invalid parameter for tag %s", tagName)
75+
}
76+
case func(string, int, int, string) error:
77+
params := strings.Split(tagParam, "-")
78+
if len(params) != 2 {
79+
return fmt.Errorf("invalid parameter for tag %s", tagName)
80+
}
81+
min, err := strconv.Atoi(params[0])
82+
if err != nil {
83+
return fmt.Errorf("invalid parameter for tag %s", tagName)
84+
}
85+
86+
max, err := strconv.Atoi(params[1])
87+
if err != nil {
88+
return fmt.Errorf("invalid parameter for tag %s", tagName)
89+
}
90+
errorMsg := getMessage(tagName, fieldName, min, max)
91+
if err := validator(fmt.Sprint(value), min, max, errorMsg); err != nil {
92+
return err
93+
} else {
94+
95+
}
96+
97+
}
98+
}
99+
}
100+
}
101+
return nil
102+
}
103+
104+
func getMessage(tagName, fieldName string, args ...interface{}) string {
105+
errorMsgTemplate := data[tagName]["error_msg"]
106+
return fmt.Sprintf(errorMsgTemplate, append([]interface{}{fieldName}, args...)...)
107+
}

0 commit comments

Comments
 (0)