Go-sql-动态生成where

该博客介绍了如何在Go语言中利用反射(reflect)包来生成基于结构体字段的动态WHERE子句,并处理不同类型的查询条件,如LIKE、BETWEEN等。同时,文章也指出了在使用BETWEEN条件时需要注意的事项,例如参数必须成对出现且顺序要正确。此外,还提供了一个测试用例展示了如何使用这个功能。
摘要由CSDN通过智能技术生成

//主方法
func GenWhereByStruct(in interface{})(string,[]interface{}){
    vValue :=reflect.ValueOf(in)
    vType :=reflect.TypeOf(in)
    var tagTmp =""
    var whereMap = make([][]string,0)
    var args = make([]interface{},0)

    for i:=0;i<vValue.NumField();i++{
        tagTmp = vType.Field(i).Tag.Get("column")
        if tagTmp =="-"||tagTmp==""{
            continue
        }
        cons :=strings.Split(tagTmp,",")
        if !IfZero(vValue.Field(i).Interface()) {
            if cons[2]=="*like"{
                cons[2] = "like"
                args = append(args, "%"+vValue.Field(i).Interface().(string))
            }else if cons[2]=="like*"{
                cons[2] = "like"
                args = append(args, vValue.Field(i).Interface().(string)+"%")
            }else if cons[2]=="*like*" || cons[2]=="like"{
                cons[2] = "like"
                args = append(args, "%"+vValue.Field(i).Interface().(string)+"%")
            }else{
                args = append(args, vValue.Field(i).Interface())
            }

            if len(whereMap)==0 {
                whereMap = append(whereMap,[]string{
                    "",cons[1],cons[2],
                })
            }else{
                whereMap = append(whereMap,[]string{
                    cons[0],cons[1],cons[2],
                })
            }

            if cons[2] == "between"{
                i++
                args = append(args,vValue.Field(i).Interface())
            }
        }
    }
    where :=GenWhere(whereMap)
    return where,args
}

//辅方法
//generate where through a where [][]string
func GenWhere(whereMap [][]string)string {
    rs:=""
    if len(whereMap) != 0 {
        rs = rs + " where "
        for _, v := range whereMap {
            //v[0]表示性质,and 还是or,v[1]表示field,比如name,age,v[2]表示条件符号,=,>,<,<>,like
            if v[2] == "between" {
                rs = rs + " " + v[0] + " " + v[1] + " " + "between" + " " + "?" + " " + "and" + " " + "?" + " "
                continue
            }
            if v[2] == "in" {
                rs = rs + " " + v[0] + " " + v[1] + " " + "in" + " " +v[3]
                continue
            }
            rs = rs + " " + v[0] + " " + v[1] + " " + v[2] + " " + "?"
        }
    }
    return rs
}

func IfZero(arg interface{}) bool {
    if arg == nil {
        return true
    }
    switch v := arg.(type) {
    case int, float64, int32, int16, int64, float32:
        if v == 0 {
            return true
        }
    case string:
        if v == "" || v == "%%" || v == "%" {
            return true
        }
    case *string, *int, *int64, *int32, *int16, *int8, *float32, *float64:
        if v == nil {
            return true
        }
    case time.Time:
        return v.IsZero()
    default:
        return false
    }
    return false
}

func RemoveZero(slice []interface{}) []interface{} {
    if len(slice) == 0 {
        return slice
    }
    for i, v := range slice {
        if IfZero(v) {
            slice = append(slice[:i], slice[i+1:]...)
            return RemoveZero(slice)
            break
        }
    }
    return slice
}

 使用:

注意事项:
1. between的参数必须两个,即AgeMin/Start和AgeMax/Stop必须同时存在或者同时没有,违反了此条件,where语句依然正确,args会不准确
2. between参数必须小的声明在大的上面,即不可定义成{AgeMax,AgeMin}
3. Like参数’*like’匹配%xxx,*like*和’like’匹配%xxx%,’like*’匹配xxx%

func TestGenWhereByStruct(t *testing.T) {
    type Tmp struct{
        Addr string `column:"and,addr,like*"`
        Desc string `column:"and,desc,like"`
        Job string`column:"and,job,*like"`
        Name string `column:"and,name,="`
        Sal float32 `column:"and,sal,>"`
        AgeMin int`column:"or,age,between"`
        AgeMax int `column:"or,age,between"`
        Start time.Time `column:"and,created,between"`
        Stop time.Time `column:"and,created,between"`
        Jump string `column:"-"`
    }
    var tmp = Tmp{
        Addr:"earth",
        Name:"ft",
        Sal:333,
        AgeMin:9,
        AgeMax:18,
        Desc:"happ",
        Job:"engineer",
        Jump:"jump",
    }

    t.Log(GenWhereByStruct(tmp))
}
 where   addr like ? and desc like ? and job like ? and name = ? and sal > ? or age between ? and ?  [earth% %happ% %engineer ft 333 9 18]

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值