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-12-24MongoDB资料:新手入门完全指南
- 2024-12-20go-zero 框架的 RPC 服务 启动start和停止 底层是怎么实现的?-icode9专业技术文章分享
- 2024-12-19Go-Zero 框架的 RPC 服务启动和停止的基本机制和过程是怎么实现的?-icode9专业技术文章分享
- 2024-12-18怎么在golang中使用gRPC测试mock数据?-icode9专业技术文章分享
- 2024-12-15掌握PageRank算法核心!你离Google优化高手只差一步!
- 2024-12-15GORM 中的标签 gorm:"index"是什么?-icode9专业技术文章分享
- 2024-12-11怎么在 Go 语言中获取 Open vSwitch (OVS) 的桥接信息(Bridge)?-icode9专业技术文章分享
- 2024-12-11怎么用Go 语言的库来与 Open vSwitch 进行交互?-icode9专业技术文章分享
- 2024-12-11怎么在 go-zero 项目中发送阿里云短信?-icode9专业技术文章分享
- 2024-12-11怎么使用阿里云 Go SDK (alibaba-cloud-sdk-go) 发送短信?-icode9专业技术文章分享