Skip to content

Commit 8ab06bd

Browse files
committed
feat: update sliceg pkg and validator pkg
1 parent 92803d4 commit 8ab06bd

File tree

7 files changed

+252
-112
lines changed

7 files changed

+252
-112
lines changed

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,8 @@ func BinarySearch[T constraints.Ordered](x []T, target T) (int, bool)
500500
func BinarySearchFunc[E, T any](x []E, target T, cmp func(a E, b T) int) (int, bool)
501501
func Clip[T any](s []T) []T
502502
func Clone[T any](s []T, needInit ...bool) []T
503+
func Compact[T comparable](s []T) []T
504+
func CompactFunc[T any](s []T, f func(v T) bool) []T
503505
func Contain[T comparable](s []T, v T) bool
504506
func ContainFunc[T any](s []T, f func(v T) bool) bool
505507
func Count[T comparable](s []T) map[T]int
@@ -614,4 +616,10 @@ type IdCard
614616
type USCC
615617
func NewUSCC(uscc string) USCC
616618
func (uscc USCC) IsValid() bool
619+
type Validator
620+
func MustNewValidator() *Validator
621+
func NewValidator() (*Validator, error)
622+
func (v *Validator) Translate(err error) error
623+
func (v *Validator) TranslateAll(err error) error
624+
func (v *Validator) Validate(r *http.Request, data any) error
617625
```

go.mod

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ require (
1717
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
1818
github.com/leodido/go-urn v1.4.0 // indirect
1919
github.com/pmezard/go-difflib v1.0.0 // indirect
20-
golang.org/x/crypto v0.19.0 // indirect
21-
golang.org/x/net v0.21.0 // indirect
22-
golang.org/x/sys v0.17.0 // indirect
20+
golang.org/x/crypto v0.21.0 // indirect
21+
golang.org/x/net v0.22.0 // indirect
22+
golang.org/x/sys v0.18.0 // indirect
2323
golang.org/x/text v0.14.0 // indirect
2424
gopkg.in/yaml.v3 v3.0.1 // indirect
2525
)

go.sum

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,14 @@ github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5g
1919
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
2020
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
2121
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
22-
golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
23-
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
22+
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
23+
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
2424
golang.org/x/exp v0.0.0-20230420155350-5d9e357047b1 h1:esPLYTcXPu8wpTcWCNGwSDTodgJwTTFNfeELKb4ewTg=
2525
golang.org/x/exp v0.0.0-20230420155350-5d9e357047b1/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
26-
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
27-
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
28-
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
29-
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
26+
golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
27+
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
28+
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
29+
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
3030
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
3131
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
3232
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=

sliceg/sliceg.go

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ func Extract[T any](s []T, n int) []T {
166166
return es
167167
}
168168

169-
// Fill returns slice filled with v,
169+
// Fill returns the slice filled with v,
170170
// where n is the number of v should be filled.
171171
func Fill[T any](v T, n int) []T {
172172
if n < 0 {
@@ -282,6 +282,33 @@ func SubsetFunc[T any](slice, subset []T, cmp func(a, b T) int) bool {
282282
return true
283283
}
284284

285+
// Compact returns the slice that all zero values removed.
286+
func Compact[T comparable](s []T) []T {
287+
var zero T
288+
cs := make([]T, 0, len(s))
289+
290+
for _, v := range s {
291+
if v != zero {
292+
cs = append(cs, v)
293+
}
294+
}
295+
296+
return cs
297+
}
298+
299+
// CompactFunc returns the slice that all satisfies f(v) values removed.
300+
func CompactFunc[T any](s []T, f func(v T) bool) []T {
301+
cs := make([]T, 0, len(s))
302+
303+
for _, v := range s {
304+
if !f(v) {
305+
cs = append(cs, v)
306+
}
307+
}
308+
309+
return cs
310+
}
311+
285312
// Clone returns a copy of the slice.
286313
// The elements are copied using assignment, so this is a shallow clone.
287314
func Clone[T any](s []T, needInit ...bool) []T {

sliceg/sliceg_test.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -752,6 +752,34 @@ func TestSubsetFunc(t *testing.T) {
752752
assert.False(t, SubsetFunc(s2, []string{"y", "o", "u"}, strings.Compare))
753753
}
754754

755+
func TestCompact(t *testing.T) {
756+
s1 := []int64{3, 0, 6, 0, 9, 0}
757+
assert.Equal(t, []int64{3, 6, 9}, Compact(s1))
758+
759+
s2 := []string{"a", "", "", "b", "", "c"}
760+
assert.Equal(t, []string{"a", "b", "c"}, Compact(s2))
761+
762+
s3 := []string{"", "", "", "a"}
763+
assert.Equal(t, []string{"a"}, Compact(s3))
764+
}
765+
766+
func TestCompactFunc(t *testing.T) {
767+
s1 := []int64{3, 0, 6, 0, 9, 0}
768+
assert.Equal(t, []int64{3, 6, 9}, CompactFunc(s1, func(v int64) bool {
769+
return v == 0
770+
}))
771+
772+
s2 := []string{"a", "", "", "b", "", "c"}
773+
assert.Equal(t, []string{"a", "b", "c"}, CompactFunc(s2, func(v string) bool {
774+
return v == ""
775+
}))
776+
777+
s3 := []string{"", "", "", "a"}
778+
assert.Equal(t, []string{"a"}, CompactFunc(s3, func(v string) bool {
779+
return v == ""
780+
}))
781+
}
782+
755783
func TestClone(t *testing.T) {
756784
s1 := []int{1, 2, 3}
757785
s2 := Clone(s1)

validator/validator.go

Lines changed: 115 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package validator
22

33
import (
44
"errors"
5+
"net/http"
56
"reflect"
67
"regexp"
78
"strings"
@@ -12,6 +13,9 @@ import (
1213
zht "github.com/go-playground/validator/v10/translations/zh"
1314
)
1415

16+
// ErrUnexpected unexpected error.
17+
var ErrUnexpected = errors.New("参数校验出错")
18+
1519
const (
1620
bankcardRegexString = "^[0-9]{15,19}$"
1721
corpaccountRegexString = "^[0-9]{9,25}$"
@@ -20,11 +24,7 @@ const (
2024
)
2125

2226
var (
23-
// ErrUnexpected unexpected error.
24-
ErrUnexpected = errors.New("参数校验出错")
25-
26-
ti ut.Translator
27-
vi *validator.Validate
27+
v = MustNewValidator()
2828

2929
bankcardRegex = regexp.MustCompile(bankcardRegexString)
3030
corpaccountRegex = regexp.MustCompile(corpaccountRegexString)
@@ -39,13 +39,15 @@ var (
3939
"PATCH": {},
4040
"OPTIONS": {},
4141
}
42+
4243
validatorFuncMap = map[string]validator.Func{
4344
"idcard": idcard,
4445
"bankcard": bankcard,
4546
"uscc": uscc,
4647
"corpaccount": corpaccount,
4748
"httpmethod": httpmethod,
4849
}
50+
4951
defaultTags = []string{
5052
"skip_unless",
5153
"eq_ignore_case",
@@ -113,6 +115,107 @@ var (
113115
}
114116
)
115117

118+
// Validator represents the validator structure.
119+
type Validator struct {
120+
V *validator.Validate
121+
T ut.Translator
122+
}
123+
124+
// NewValidator new a validator.
125+
func NewValidator() (*Validator, error) {
126+
vi := validator.New()
127+
vi.SetTagName("validate")
128+
vi.RegisterTagNameFunc(getLabelTagName)
129+
130+
zhi := zh.New()
131+
uti := ut.New(zhi)
132+
ti, _ := uti.GetTranslator("zh")
133+
134+
if err := zht.RegisterDefaultTranslations(vi, ti); err != nil {
135+
return nil, err
136+
}
137+
138+
for tag, fn := range validatorFuncMap {
139+
if err := vi.RegisterValidation(tag, fn); err != nil {
140+
return nil, err
141+
}
142+
if err := registerTranslation(tag, vi, ti, true); err != nil {
143+
return nil, err
144+
}
145+
}
146+
147+
for _, defaultTag := range defaultTags {
148+
if err := registerTranslation(defaultTag, vi, ti, false); err != nil {
149+
return nil, err
150+
}
151+
}
152+
153+
return &Validator{
154+
V: vi,
155+
T: ti,
156+
}, nil
157+
}
158+
159+
// MustNewValidator must new a validator.
160+
func MustNewValidator() *Validator {
161+
v, err := NewValidator()
162+
if err != nil {
163+
panic(err)
164+
}
165+
166+
return v
167+
}
168+
169+
// Validate validates the request and parsed data.
170+
func (v *Validator) Validate(r *http.Request, data any) error {
171+
return v.Translate(v.V.Struct(data))
172+
}
173+
174+
// Translate translates the validation errors.
175+
func (v *Validator) Translate(err error) error {
176+
if err != nil {
177+
var (
178+
es validateErrors
179+
ves validator.ValidationErrors
180+
)
181+
182+
if errors.As(err, &ves) {
183+
for _, ve := range ves {
184+
es = append(es, ve.Translate(v.T))
185+
}
186+
}
187+
188+
return es
189+
}
190+
191+
return nil
192+
}
193+
194+
// TranslateAll translates all validation errors.
195+
func (v *Validator) TranslateAll(err error) error {
196+
if err != nil {
197+
var (
198+
es []string
199+
ves validator.ValidationErrors
200+
)
201+
202+
if errors.As(err, &ves) {
203+
for _, ve := range ves {
204+
es = append(es, ve.Translate(v.T))
205+
}
206+
}
207+
208+
if len(es) == 0 {
209+
return ErrUnexpected
210+
}
211+
212+
return errors.New(strings.Join(es, ","))
213+
}
214+
215+
return nil
216+
}
217+
218+
// validateErrors represents the validation error strings.
116219
type validateErrors []string
117220

118221
// Error returns the validation error string and implement the error interface,
@@ -127,6 +230,10 @@ func (ves validateErrors) Error() string {
127230

128231
// ParseErr parses the content of validation error.
129232
func ParseErr(err error) string {
233+
if err == nil {
234+
return ""
235+
}
236+
130237
var ves validateErrors
131238
ok := errors.As(err, &ves)
132239
if ok && len(ves) > 0 {
@@ -136,66 +243,19 @@ func ParseErr(err error) string {
136243
return err.Error()
137244
}
138245

139-
func init() {
140-
var err error
141-
vi = validator.New()
142-
vi.SetTagName("validate")
143-
vi.RegisterTagNameFunc(getLabelTagName)
144-
145-
zhi := zh.New()
146-
uti := ut.New(zhi)
147-
ti, _ = uti.GetTranslator("zh")
148-
149-
err = zht.RegisterDefaultTranslations(vi, ti)
150-
checkErr(err)
151-
152-
for tag, fn := range validatorFuncMap {
153-
err = vi.RegisterValidation(tag, fn)
154-
checkErr(err)
155-
err = registerTranslation(tag, vi, ti, true)
156-
checkErr(err)
157-
}
158-
for _, defaultTag := range defaultTags {
159-
_ = registerTranslation(defaultTag, vi, ti, false)
160-
}
161-
}
162-
163246
// Verify checks the data validity of the exportable field of the structure according to the validate tag.
164247
func Verify(obj interface{}) error {
165-
return convertErr(vi.Struct(obj))
248+
return v.Translate(v.V.Struct(obj))
166249
}
167250

168251
// VerifyVar checks the data validity of the field according to the validate tag.
169252
func VerifyVar(field interface{}, tag string) error {
170-
return convertErr(vi.Var(field, tag))
253+
return v.Translate(v.V.Var(field, tag))
171254
}
172255

173256
// VerifyVarWithValue checks the data validity of the field against another field according to the validate tag.
174257
func VerifyVarWithValue(field, other interface{}, tag string) error {
175-
return convertErr(vi.VarWithValue(field, other, tag))
176-
}
177-
178-
// convertErr converts err to validation error.
179-
func convertErr(err error) error {
180-
if err != nil {
181-
var (
182-
ves validateErrors
183-
ive *validator.InvalidValidationError
184-
ve validator.ValidationErrors
185-
)
186-
if errors.As(err, &ive) {
187-
return ves
188-
}
189-
if errors.As(err, &ve) {
190-
for _, err := range ve {
191-
ves = append(ves, err.Translate(ti))
192-
}
193-
}
194-
195-
return ves
196-
}
197-
198-
return nil
258+
return v.Translate(v.V.VarWithValue(field, other, tag))
199259
}
200260

201261
// getLabelTagName gets the label name.
@@ -259,10 +319,3 @@ func httpmethod(fl validator.FieldLevel) bool {
259319
_, ok := httpMethodMap[strings.ToUpper(fl.Field().String())]
260320
return ok
261321
}
262-
263-
// checkErr checks the err.
264-
func checkErr(err error) {
265-
if err != nil {
266-
panic(err)
267-
}
268-
}

0 commit comments

Comments
 (0)