美文网首页
golang对结构体里的宽字段进行字典序排序

golang对结构体里的宽字段进行字典序排序

作者: 杜子龙 | 来源:发表于2020-08-08 22:03 被阅读0次

    现在业务有一个异步查询的需求,需要把不同的请求缓存起来,需要对同一类请求封装成request struct,放到map的key中,如果请求中都是基础类型还好说,可以直接使用golang原生的序列化包,对struct序列化之后,是会自动按照struct中字段的字典序排序。但这里有个问题,就是前端请求中的某个字段是个json宽字段,因此这里就不适合直接使用序列化工具,需要遍历struct,找出其中的宽字段,先反序列化再序列化即可。但这样比较麻烦,需要事先知道结构体中有哪些宽字段,以及结构体里嵌套结构体里的宽字段,所以这里基于反射实现了此功能,目前只接受入参为指针,后续待优化。

    func SortedStruct(i interface{}){//暂时只接受指针
        v := reflect.ValueOf(i)
        if v.Kind() == reflect.Ptr{
            deepSortedStruct(v)
        }else{//TODO 这里有bug
            SortedStruct(&i)
        }
    }
    
    func deepSortedStruct(v reflect.Value){
        switch v.Kind() {
        case reflect.String:
            v.SetString(sortStr(v.String()))
        case reflect.Array:
            for i := 0; i < v.Len(); i++{
                deepSortedStruct(v.Index(i))
            }
        case reflect.Slice:
            if v.IsNil(){
                return
            }
            for i := 0; i < v.Len(); i++{
                deepSortedStruct(v.Index(i))
            }
        case reflect.Interface:
            if v.IsNil(){
                return
            }
            deepSortedStruct(v.Elem())
        case reflect.Ptr:
            deepSortedStruct(v.Elem())
        case reflect.Struct:
            for i := 0; i < v.NumField(); i++{
                deepSortedStruct(v.Field(i))
            }
        case reflect.Map:
            if v.IsNil(){
                return
            }
            for _, key := range v.MapKeys(){
                deepSortedStruct(v.MapIndex(key))
            }
        }
    }
    
    func sortStr(str string)string{
        var tmp interface{}
        err := json.Unmarshal([]byte(str), &tmp)
        if err != nil{
            return str
        }
        bytes, _ := json.Marshal(tmp)
        return string(bytes)
    }
    

    相关文章

      网友评论

          本文标题:golang对结构体里的宽字段进行字典序排序

          本文链接:https://www.haomeiwen.com/subject/gulkdktx.html