gvalid包增加struct tag的校验规则、自定义错误提示信息绑定的支持特性

This commit is contained in:
John
2018-08-11 21:09:42 +08:00
parent 94df8da71a
commit 25e3e0433c
12 changed files with 89 additions and 232 deletions

3
TODO
View File

@ -10,7 +10,6 @@ ghttp.Response增加输出内容后自动退出当前请求机制不需要用
Cookie&Session数据池化处理
ghttp.Client增加proxy特性
gtime增加对时区转换的封装并简化失去转换时对类似+80500时区的支持
gvalid包增加tag与校验规则绑定的支持特性
ghttp获取参数支持直接转struct功能
map转struct增加对tag的支持
gcache检查在i386下的int64->int转换问题
@ -48,5 +47,5 @@ DONE:
28. ORM增加获取被执行的sql语句的方法
29. gdb增加查询缓存特性
30. gpage分页增加对自定义后缀的支持如:2.html, 2.php等等
31. gvalid包增加struct tag的校验规则、自定义错误提示信息绑定的支持特性

View File

@ -17,16 +17,19 @@ import (
)
// 格式化打印变量(类似于PHP-vardump)
func Dump(i interface{}) {
buffer := &bytes.Buffer{}
encoder := json.NewEncoder(buffer)
encoder.SetEscapeHTML(false)
encoder.SetIndent("", "\t")
if err := encoder.Encode(i); err == nil {
fmt.Println(buffer.String())
} else {
fmt.Errorf("%s\n", err.Error())
func Dump(i...interface{}) {
for _, v := range i {
buffer := &bytes.Buffer{}
encoder := json.NewEncoder(buffer)
encoder.SetEscapeHTML(false)
encoder.SetIndent("", "\t")
if err := encoder.Encode(v); err == nil {
fmt.Print(buffer.String())
} else {
fmt.Errorf("%s", err.Error())
}
}
fmt.Println()
}
// 将map键值对映射到对应的struct对象属性上需要注意

View File

@ -381,7 +381,7 @@ func CheckMap(params map[string]interface{}, rules map[string]string, msgs...map
var value interface{}
// 自定义消息,非必须参数,因此这里需要做判断
customMsgs := make(map[string]interface{})
if len(msgs) > 0 {
if len(msgs) > 0 && len(msgs[0]) > 0 {
customMsgs = msgs[0]
}
errorMsgs := make(map[string]map[string]string)
@ -421,8 +421,44 @@ func CheckMap(params map[string]interface{}, rules map[string]string, msgs...map
}
// 校验struct对象属性object参数也可以是一个指向对象的指针返回值同CheckMap方法
func CheckStruct(object interface{}, rules map[string]string, msgs...map[string]interface{}) map[string]map[string]string {
return CheckMap(structs.Map(object), rules, msgs...)
func CheckStruct(st interface{}, rules map[string]string, msgs...map[string]interface{}) map[string]map[string]string {
fields := structs.Fields(st)
if rules == nil {
rules = make(map[string]string)
}
params := make(map[string]interface{})
errMsgs := (map[string]interface{})(nil)
if len(msgs) == 0 {
errMsgs = make(map[string]interface{})
} else {
errMsgs = msgs[0]
}
for _, field := range fields {
params[field.Name()] = field.Value()
if tag := field.Tag("gvalid"); tag != "" {
match, _ := gregex.MatchString(`([^#]+)#{0,1}(.*)`, tag)
// 校验规则
if _, ok := rules[field.Name()]; !ok {
rules[field.Name()] = match[1]
}
// 错误提示
if match[2] != "" {
ruleArray := strings.Split(match[1], "|")
msgArray := strings.Split(match[2], "|")
for k, v := range ruleArray {
if len(msgArray[k]) == 0 {
continue
}
array := strings.Split(v, ":")
if _, ok := errMsgs[field.Name()]; !ok {
errMsgs[field.Name()] = make(map[string]string)
}
errMsgs[field.Name()].(map[string]string)[array[0]] = msgArray[k]
}
}
}
}
return CheckMap(params, rules, errMsgs)
}
// 检测单条数据的规则其中params参数为非必须参数可以传递所有的校验参数进来进行多参数对比(部分校验规则需要)

View File

@ -1,15 +0,0 @@
package main
import (
"gitee.com/johng/gf/g"
"gitee.com/johng/gf/g/net/ghttp"
)
func main() {
s := g.Server()
s.BindHandler("/", func(r *ghttp.Request){
r.Response.Writeln("哈喽世界!")
})
s.SetPort(8199)
s.Run()
}

View File

@ -1,27 +0,0 @@
package main
import (
"gitee.com/johng/gf/g"
"gitee.com/johng/gf/g/net/ghttp"
"gitee.com/johng/gf/g/database/gredis"
)
func main() {
s := g.Server()
s.BindHandler("/", func(r *ghttp.Request) {
redis := gredis.New(gredis.Config{
Host: "redis-service",
Port: 9999,
})
defer redis.Close()
v, err := redis.Do("GET", "k")
r.Response.Writeln(v)
r.Response.Writeln(err)
v, err = redis.Do("SET", "k", "v")
r.Response.Writeln(v)
r.Response.Writeln(err)
})
s.Run()
}

View File

@ -1,19 +0,0 @@
package main
import (
"fmt"
"net/http"
"github.com/tabalt/gracehttp"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "hello world")
})
err := gracehttp.ListenAndServe(":8888", nil)
if err != nil {
fmt.Println(err)
}
}

View File

@ -1,57 +0,0 @@
// Copyright 2017 gf Author(https://gitee.com/johng/gf). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://gitee.com/johng/gf.
// go test *.go -bench=".*"
package test
import (
"testing"
)
var m1 = make(map[int]int)
var m2 = make(map[interface{}]interface{})
func BenchmarkMapIntInt_Set(b *testing.B) {
for i := 0; i < b.N; i++ {
m1[i] = i
}
}
func BenchmarkMapIntInt_Search(b *testing.B) {
for i := 0; i < b.N; i++ {
if _, ok := m1[i]; ok {
}
}
}
func BenchmarkMapIntInt_Remove(b *testing.B) {
for i := 0; i < b.N; i++ {
delete(m1, i)
}
}
func BenchmarkMapInterface_Set(b *testing.B) {
for i := 0; i < b.N; i++ {
m2[i] = i
}
}
func BenchmarkMapInterface_Search(b *testing.B) {
for i := 0; i < b.N; i++ {
if _, ok := m2[i]; ok {
}
}
}
func BenchmarkMapInterface_Remove(b *testing.B) {
for i := 0; i < b.N; i++ {
delete(m2, i)
}
}

View File

@ -1,60 +0,0 @@
package main
import (
"fmt"
//"reflect"
"reflect"
)
//import "reflect"
type gtInterface interface {
Run()
}
type st struct {
age int
Name string
}
type mySt struct {
st
}
func (_ st) Echo(str string) {
fmt.Printf("echo(%s)\n", str)
}
func (_ *st) Echo2(str string) {
fmt.Printf("echo2(%s)\n", str)
}
func (_ st) Echo3() {
fmt.Println("echo3()")
}
func Echo3() {
fmt.Println("echo3()")
}
type DefaultFunc func()
func Call(i DefaultFunc) {
i()
//reflect.ValueOf(i).Call([]reflect.Value{})
}
func main() {
s := st {16,"john"}
//p := reflect.ValueOf("halloo")
v := reflect.ValueOf(s)
//v2 := reflect.ValueOf(&s)
//// 调用st结构体的方法
//v.MethodByName("Echo").Call([]reflect.Value{p})
//// 我们需要调用的是实体结构体指针的方法注意v2与v2的区别以及方法定义的区别
//v2.MethodByName("Echo2").Call([]reflect.Value{p})
//v.MethodByName()
fmt.Println(v.FieldByName("name"))
}

View File

@ -1,16 +0,0 @@
package sleep
import (
"time"
"gitee.com/johng/gf/g/os/glog"
)
func init () {
glog.Println("sleep package importing")
time.Sleep(3*time.Second)
glog.Println("sleep package imported")
}
func Test() {
glog.Println("Test")
}

View File

@ -1,22 +0,0 @@
package main
import (
"testing"
"strings"
)
var s = "arwerwerwerwerwerwrwerwerwerwersefsdgsdfgsddsfgsdfsd timeout"
func Benchmark_Contains(b *testing.B) {
for i := 0; i < b.N; i ++ {
strings.Contains(s, "timeout")
}
}
func Benchmark_EqualFold(b *testing.B) {
for i := 0; i < b.N; i ++ {
strings.EqualFold(s[len(s) - 7:], "timeout")
}
}

View File

@ -1,8 +1,8 @@
package main
import (
"fmt"
"gitee.com/johng/gf/g/util/gvalid"
"gitee.com/johng/gf/g/util/gutil"
)
func main() {
@ -60,6 +60,6 @@ func main() {
"same" : "两次密码输入不相等",
},
}
fmt.Println(gvalid.CheckMap(params, rules, msgs))
gutil.Dump(gvalid.CheckMap(params, rules, msgs))
// map[passport:map[length:账号长度应当在6到16之间] password:map[same:两次密码输入不相等]]
}

View File

@ -0,0 +1,35 @@
package main
import (
"gitee.com/johng/gf/g/util/gutil"
"gitee.com/johng/gf/g/util/gvalid"
)
type User struct {
Uid int `gvalid:"integer|min:1"`
Name string `gvalid:"required|length:6,30#请输入用户名称|用户名称长度非法"`
Pass1 string `gvalid:"required|password3"`
Pass2 string `gvalid:"required|password3|same:Pass1#||两次密码不一致,请重新输入"`
}
func main() {
user := &User{
Name : "john",
Pass1: "Abc123!@#",
Pass2: "123",
}
// 使用结构体定义的校验规则和错误提示进行校验
gutil.Dump(gvalid.CheckStruct(user, nil))
// 自定义校验规则和错误提示,对定义的特定校验规则和错误提示进行覆盖
rules := map[string]string {
"Uid" : "required",
}
msgs := map[string]interface{} {
"Pass2" : map[string]string {
"password3" : "名称不能为空",
},
}
gutil.Dump(gvalid.CheckStruct(user, rules, msgs))
}