项目场景:
要对数个数据库表中的数据进行加密/解密,需针对每个数据表建立结构体,针对不同的结构体写不同的解密方法,此过程十分繁琐,但必不可少。
# 解决方案: 通过使用反射,对结构体进行动态的获取属性,修改属性等操作可大大减少代码量。 ```go package decode import ( "DecodeService/util" "fmt" "reflect" "strconv" "strings" ) const tag = "json" func DeCommon(o interface{}) { // 获取类型 t := reflect.TypeOf(o) // 因为传入的是指针所以需要这步 t = t.Elem() // 获取值 v := reflect.ValueOf(o) // 因为传入的是指针所以需要这步 v = v.Elem() // 可以获取所有属性 // 获取结构体字段个数:t.NumField() for i := 0; i < t.NumField(); i++ { // 取每个不为空的字段 if !v.Field(i).IsZero() { f := t.Field(i) tag := f.Tag.Get(tag) fv := v.Field(i).String() if strings.HasPrefix(tag, "enc") && fv != "0" { fmt.Println("- decode - ", fv) var plaintext string plaintext = util.DecodeEDE3WithKey(fv) tagName := "de" + tag[3:] setValue(o, tagName, plaintext) } } } } // 可以运行 func setValue(o interface{}, tagName, plaintext string) { v := reflect.ValueOf(o) v = v.Elem() t := reflect.TypeOf(o) t = t.Elem() var f reflect.Value for i := 0; i < t.NumField(); i++ { if t.Field(i).Tag.Get("json") == tagName { f = v.Field(i) } } if !f.IsValid() { fmt.Println("ERROR : Not find field that tag is ", tagName) } if f.Kind() == reflect.String { f.SetString(plaintext) } if f.Kind() == reflect.Int { i, err := strconv.Atoi(plaintext) if err != nil { fmt.Println(err) } f.SetInt(int64(i)) } } ```