GOLANG Web请求参数验证

怪咖_OOP · · 702 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

基于golang web项目实际开发中在controller层对客户端请求参数进行验证,这样导致controller层代码冗余度非常高,影响开发效率。代码示例:

    feedback := &mysql_model.OfbankFeedback{}
    err := json.Unmarshal(body, feedback)
    feedback.FStatus=1
    feedback.CreateTime=time.Now()
    if err != nil {
        resp := apiservice.GenerateResponse(0, "请求参数有误", "")
        rw.Write([]byte(resp))
        return
    }
    if feedback.Phone=="" {
        resp := apiservice.GenerateResponse(0, "参数phone不能为空", "")
        rw.Write([]byte(resp))
        return
    }
    if feedback.Contacts=="" {
        resp := apiservice.GenerateResponse(0, "参数contacts不能为空", "")
        rw.Write([]byte(resp))
        return
    }
    if feedback.FType==0 {
        resp := apiservice.GenerateResponse(0, "参数fType不能为空", "")
        rw.Write([]byte(resp))
        return
    }
    if feedback.Img==""&&feedback.Content=="" {
        resp := apiservice.GenerateResponse(0, "参数img或content不能同时为空", "")
        rw.Write([]byte(resp))
        return
    }

代码冗余度高?影响开发效率?如何解决?

目前有很多web框架(beego、faygo等)支持结构体参数验证;为了解决项目管理上的问题引入一个框架且框架中参数验证规则扩展性不是很好,个人感觉不是很优雅;于是自己写了一个结构体参数验证工具(struct_util.go)

代码示例:
/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: yangzhao
 * Date: 2018-07-17
 * Time: 11:08
 */
package utils

import (
    "reflect"
    "errors"
    "strings"
    "strconv"
)
//自定义验证规则
const (
    NOT_EMPTY = "NotEmpty" //字符串不能为空
    INT_MAX = "int-max" //int最大值
    INT_MIN = "int-min" //int最小值
    TYPE = "type" //类型
    STR_MAX_LENGTH = "str-max-len" //字符串最大长度
    STR_MIN_LENGTH = "str-min-len" //字符串最小长度
    STR_LENGTH = "str-len" //字符串长度
    RANGE = "range" //元素必须在合适的范围内 例:1-100
)
//对外暴露结构体验证函数
func StructValidate(bean interface{}) error {
    fields := reflect.ValueOf(bean).Elem()
    for i := 0; i < fields.NumField(); i++ {
        field := fields.Type().Field(i)
        valid := field.Tag.Get("valid")
        if valid == "" {
            continue
        }
        value := fields.FieldByName(field.Name)
        err := fieldValidate(field.Name, valid, value)
        if err != nil {
            return err
        }
    }
    return nil
}
//属性验证
func fieldValidate(fieldName, valid string, value reflect.Value) error {
    valids := strings.Split(valid, " ")
    for _, valid := range valids {

        if strings.Index(valid, TYPE) != -1 {
            v := value.Type().Name()
            split := strings.Split(valid, "=")
            t := split[1]
            if v != t {
                return errors.New(fieldName + " type must is " + t)
            }
        }

        if strings.Index(valid, NOT_EMPTY) != -1 {
            str := value.String()
            if str == "" {
                return errors.New(fieldName + " value not empty")
            }
        }
        if strings.Index(valid, INT_MIN) != -1 {
            v := value.Int()
            split := strings.Split(valid, "=")
            rule, err := strconv.Atoi(split[1])
            if err != nil {
                return errors.New(fieldName + ":验证规则有误")
            }
            if int(v) < rule {
                return errors.New(fieldName + " value must >= " + strconv.Itoa(rule))
            }
        }

        if strings.Index(valid, INT_MAX) != -1 {
            v := value.Int()
            split := strings.Split(valid, "=")
            rule, err := strconv.Atoi(split[1])
            if err != nil {
                return errors.New(fieldName + ":验证规则有误")
            }
            if int(v) > rule {

                return errors.New(fieldName + " value must <= " + strconv.Itoa(rule))
            }
        }
        //字符串特殊处理
        if value.Type().Name() == "string" {
            if strings.Index(valid, STR_LENGTH) != -1 {
                v := value.String()
                split := strings.Split(valid, "=")
                lenStr := split[1]
                length, err := strconv.Atoi(lenStr)
                if err != nil {
                    return errors.New(fieldName + " " + STR_LENGTH + " rule is error")
                }
                if len(v) != length {
                    return errors.New(fieldName + " str length  must be " + lenStr)
                }
            }
            if strings.Index(valid, STR_MAX_LENGTH) != -1 {
                v := value.String()
                split := strings.Split(valid, "=")
                lenStr := split[1]
                length, err := strconv.Atoi(lenStr)
                if err != nil {
                    return errors.New(fieldName + " " + STR_LENGTH + " rule is error")
                }
                if len(v) > length {
                    return errors.New(fieldName + " str length  <= " + lenStr)
                }
            }

            if strings.Index(valid, STR_MIN_LENGTH) != -1 {
                v := value.String()
                split := strings.Split(valid, "=")
                lenStr := split[1]
                length, err := strconv.Atoi(lenStr)
                if err != nil {
                    return errors.New(fieldName + " " + STR_LENGTH + " rule is error")
                }
                if len(v) < length {
                    return errors.New(fieldName + " str length  >= " + lenStr)
                }
            }
        }
    }
    return nil
}

以上属于原创文章,转载请注明作者@怪咖
QQ:208275451


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:怪咖_OOP

查看原文:GOLANG Web请求参数验证

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

702 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传