Go语言不同结构体相同字段名,进行值转换
2022/4/22 6:12:53
本文主要是介绍Go语言不同结构体相同字段名,进行值转换,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
问题:下面定义Student和Teacher两个结构体,如何让他们的数据值转换呢?
type Student struct { Id int `json:"id"` Name string `json:"name"` Slic []int `json:"slic"` S struct { Id int `json:"id"` Name string `json:"name"` } `json:"s"` } type Teacher struct { Id int `json:"id"` Name string `json:"name"` Slic []int `json:"slic"` S struct { Id int `json:"id"` Name string `json:"name"` } `json:"s"` }
小问题,还可以很优雅:
// StructToStruct 结构体转结构体 func StructToStruct(sourceStruct, targetStruct interface{}, cover bool) (err error) { sourceType := reflect.TypeOf(sourceStruct) targetType := reflect.TypeOf(targetStruct) if targetType.Kind() != reflect.Ptr { err = errors.New("转换失败,目标结构体不是指针") return } for sourceType.Kind() == reflect.Ptr { sourceType = sourceType.Elem() } for targetType.Kind() == reflect.Ptr { targetType = targetType.Elem() } if sourceType.Kind() != reflect.Struct || targetType.Kind() != reflect.Struct { err = errors.New("转换失败,只支持转结构体") return } sourceValue := reflect.ValueOf(sourceStruct) targetValue := reflect.ValueOf(targetStruct) for sourceValue.Kind() == reflect.Ptr { sourceValue = sourceValue.Elem() } for targetValue.Kind() == reflect.Ptr { targetValue = targetValue.Elem() } ok := transformation(sourceType, targetType, sourceValue, targetValue, cover) if !ok { err = errors.New("未转换") } return } func transformation(sourceType, targetType reflect.Type, sourceValue, targetValue reflect.Value, cover bool) (isSet bool) { for sourceType.Kind() == reflect.Ptr { sourceType = sourceType.Elem() } for targetType.Kind() == reflect.Ptr { targetType = targetType.Elem() } for sourceValue.Kind() == reflect.Ptr { sourceValue = sourceValue.Elem() } for targetValue.Kind() == reflect.Ptr { targetValue = targetValue.Elem() } // 获取目标字段,只获取不为0,且可设置的字段 var targetMap = make(map[string]int, targetValue.NumField()) for i := 0; i < targetValue.NumField(); i++ { if !targetValue.Field(i).CanSet() { continue } if !cover && !isBlank(targetValue.Field(i)) { continue } targetMap[getFieldName(targetType.Field(i))] = i } if len(targetMap) == 0 { return } // 获取源数据字段 var sourceMap = make(map[string]int, sourceType.NumField()) for i := 0; i < sourceType.NumField(); i++ { name := getFieldName(sourceType.Field(i)) if _, ok := targetMap[name]; !ok { continue } sourceMap[getFieldName(sourceType.Field(i))] = i } for name, source := range sourceMap { target, ok := targetMap[name] if !ok { continue } // 不支持往下层走,后面再补充 if sourceValue.Field(source).Kind() == reflect.Ptr || sourceValue.Field(source).Kind() == reflect.Struct { ok = transformation(sourceType.Field(source).Type, targetType.Field(target).Type, sourceValue.Field(source), targetValue.Field(target), cover) if ok { if !isSet { isSet = true } continue } } if sourceType.Field(source).Type != targetType.Field(target).Type { continue } targetValue.Field(target).Set(sourceValue.Field(source)) isSet = true } return } // 获取字段tag或者name func getFieldName(t reflect.StructField) string { s := t.Tag.Get("gorm") if s != "" { s1 := strings.Split(s, ";") for i := range s1 { if strings.HasPrefix(s1[i], "column:") { s = strings.TrimSpace(s1[i][6:]) break } } if s != "" { return s } } s = t.Tag.Get("json") if s != "" { return s } return t.Name } // 判断反射的值是否为0 func isBlank(value reflect.Value) bool { switch value.Kind() { case reflect.String: return value.Len() == 0 case reflect.Bool: return !value.Bool() case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return value.Int() == 0 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return value.Uint() == 0 case reflect.Float32, reflect.Float64: return value.Float() == 0 case reflect.Interface, reflect.Ptr: return value.IsNil() } return reflect.DeepEqual(value.Interface(), reflect.Zero(value.Type()).Interface()) }
这篇关于Go语言不同结构体相同字段名,进行值转换的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-15SendGrid 的 Go 客户端库怎么实现同时向多个邮箱发送邮件?-icode9专业技术文章分享
- 2024-11-15SendGrid 的 Go 客户端库怎么设置header 和 标签tag 呢?-icode9专业技术文章分享
- 2024-11-12Cargo deny安装指路
- 2024-11-02MongoDB项目实战:从入门到初级应用
- 2024-11-01随时随地一键转录,Google Cloud 新模型 Chirp 2 让语音识别更上一层楼
- 2024-10-25Google Cloud动手实验详解:如何在Cloud Run上开发无服务器应用
- 2024-10-24AI ?先驱齐聚 BAAI 2024,发布大规模语言、多模态、具身、生物计算以及 FlagOpen 2.0 等 AI 模型创新成果。
- 2024-10-20goland工具下,如修改一个项目的标准库SDK的版本-icode9专业技术文章分享
- 2024-10-17Go学习:初学者的简单教程
- 2024-10-17Go学习:新手入门完全指南