// BindEdgeAll(rr, &[]moe.r)
func BindEdgeAll(resultSet *nebula.ResultSet, v interface{}) error {
refType := reflect.TypeOf(v)
refVal := reflect.ValueOf(v)
if refType.Kind() != reflect.Ptr {
return errors.New("类型错误 应该为&[]")
}
// 解引用看内部类型
if refType.Elem().Kind() != reflect.Slice {
return errors.New("类型错误 应该为&[]")
}
elem := refType.Elem().Elem() // 内部具体的类型
sliceVal := refVal.Elem() // 具体slice
// 建立一个新数组
newArr := make([]reflect.Value, 0)
// 建立一个item
total := resultSet.GetRowSize()
for i := 0; i < total; i++ {
// Get a row from resultSet
record, err := resultSet.GetRowValuesByIndex(i)
if err != nil {
return errors.WithStack(err)
}
edge, err := newEdge(record, elem)
if err != nil {
return errors.WithStack(err)
}
newArr = append(newArr, edge.Elem())
}
// 重写
resArr := reflect.Append(sliceVal, newArr...)
sliceVal.Set(resArr)
return nil
}
// 无中生有
func newEdge(record *nebula.Record, elemType reflect.Type) (resVal reflect.Value, err error) {
defer func() {
if error := recover(); error != nil {
err = errors.Errorf("%s", error)
}
}()
// 1. 获取struct所有的 json tag
// 2. 对应ColNames
// 3. 类型转换
// 4. 填数据
refVal := reflect.New(elemType)
refTypeElem := elemType
refValElem := refVal.Elem()
for i := 0; i < refTypeElem.NumField(); i++ {
typeElem := refTypeElem.Field(i)
structElem := refValElem.Field(i)
if !structElem.CanSet() {
continue
}
// 取tag
tag := typeElem.Tag.Get("json")
if tag == "" {
tag = typeElem.Name
}
if tag == "-" {
continue
}
col, err := record.GetValueByColName(tag)
if err != nil {
continue
}
switch typeElem.Type.Kind() {
case reflect.Float64:
f, err := col.AsFloat()
if err != nil {
continue
}
structElem.SetFloat(f)
case reflect.String:
s := strings.TrimSpace(col.String())
s = strings.Replace(s, "\"", "", -1)
structElem.SetString(s)
}
}
return refVal, err
}
// BindEdge(c, &rs)
func BindEdge(record *nebula.Record, v interface{}) error {
// 1. 获取struct所有的 json tag
// 2. 对应ColNames
// 3. 类型转换
// 4. 填数据
refType := reflect.TypeOf(v)
refVal := reflect.ValueOf(v)
if refType.Kind() != reflect.Ptr {
return errors.New("应该传入指针")
}
refTypeElem := refType.Elem()
refValElem := refVal.Elem()
if refTypeElem.NumField() == 0 {
return errors.New("模型绑定错误")
}
for i := 0; i < refTypeElem.NumField(); i++ {
typeElem := refTypeElem.Field(i)
structElem := refValElem.Field(i)
if !structElem.CanSet() {
continue
}
// 取tag
tag := typeElem.Tag.Get("json")
if tag == "" {
tag = typeElem.Name
}
if tag == "-" {
continue
}
col, err := record.GetValueByColName(tag)
if err != nil {
continue
}
switch typeElem.Type.Kind() {
case reflect.Float64:
f, err := col.AsFloat()
if err != nil {
continue
}
structElem.SetFloat(f)
case reflect.String:
s := strings.TrimSpace(col.String())
s = strings.Replace(s, "\"", "", -1)
structElem.SetString(s)
}
}
return nil
}
反射创建一个新的对象
refType := reflect.TypeOf(MockModel{})
after = reflect.New(refType).Interface() // 这是一个指针
穷尽获取struct里面所有的元素类型
func GetModelFields(v reflect.Value) []reflect.StructField {
sf := make([]reflect.StructField, 0)
if v.Type().Kind() != reflect.Struct {
panic("CDC Connector Deserialization Please pass in the structure !!!!")
}
for i := 0; i < v.NumField(); i++ {
field := v.Type().Field(i)
if field.Type.Kind() == reflect.Struct && IsInnerStruct(field) {
innerSF := GetModelFields(v.Field(i))
sf = append(sf, innerSF...)
} else {
sf = append(sf, field)
}
}
return sf
}
直接进行值赋值
switch value.Type().Kind() {
default: // 普通元素
beforeElem.FieldByName(fieldName).Set(oldBeforeElem.FieldByName(fieldName))
case reflect.Ptr: // 针对指针
beforeElem.FieldByName(fieldName).Set(reflect.New(oldBeforeElem.FieldByName(fieldName).Type().Elem()))
}