作者原创,一字一句手打,全程代码干货。如有帮助,欢迎留下足迹哦!
目录
背景
代码写的手麻了,在休息的时候突然想到一些场景,就想到了平时常见的各种UnMarshal,手不仅麻了,还痒的不行,抽了点时间随便写写实现一下,分享出来。
基本准备
构造一个结构体:
type Desc struct {
Name string
Age int
}
一些工具函数:
func getElemType(in reflect.Type) (elemType reflect.Type, isPointer bool) {
elemType = in.Elem()
isPointer = false
if elemType.Kind() == reflect.Ptr {
isPointer = true
elemType = elemType.Elem()
}
return
}
func createOne(isPointer bool, elemType reflect.Type) reflect.Value {
if isPointer {
return reflect.New(elemType)
}
return reflect.New(elemType).Elem()
}
func getReflectValueAndType(in interface{}) (reflect.Value, reflect.Type) {
value := reflect.ValueOf(in)
if value.Kind() == reflect.Ptr {
value = value.Elem()
}
return value, value.Type()
}
UnMarshal的核心逻辑
// 第一个参数是原始值,是什么类型无所谓,只要能读出来就好
func myUnMarshal(r *strings.Reader, out interface{}) (err error) {
outValue, outType := getReflectValueAndType(out)
sourceBody := ""
bs := make([]byte, 20)
for {
var n int
n, err = r.Read(bs)
if err == io.EOF || n == 0 {
break
}
if err != nil {
fmt.Println("err: ", err)
break
}
sourceBody += string(bs[:n])
}
sourceBodies := strings.Split(sourceBody, ";")
elemType, isPointer := getElemType(outType)
for _, oneBody := range sourceBodies {
fieldBodies := strings.Split(oneBody, ",")
// 创建单个对象
distVal := createOne(isPointer, elemType)
for j := 0; j < elemType.NumField(); j++ {
fmt.Println("属性名=", elemType.Field(j).Name, " 值=", len(fieldBodies[j]))
fieldType := elemType.Field(j).Type.Kind()
switch fieldType {
case reflect.String:
distVal.Field(j).SetString(fieldBodies[j])
case reflect.Int:
distInt, _ := strconv.Atoi(fieldBodies[j])
fmt.Println("distInt = ", distInt)
distVal.Field(j).SetInt(int64(distInt))
}
}
fmt.Printf("-->%+v\n", distVal)
// 设置对象到切片
outValue.Set(reflect.Append(outValue, distVal))
}
return
}
调用:
var desc []Desc
b := strings.NewReader(`王1,99;王2,98;王3,97`)
myUnMarshal(b, &desc)
fmt.Println(desc)
看效果:
属性名= Name 值= 4
属性名= Age 值= 2
distInt = 99
-->{Name:王1 Age:99}
属性名= Name 值= 4
属性名= Age 值= 2
distInt = 98
-->{Name:王2 Age:98}
属性名= Name 值= 4
属性名= Age 值= 2
distInt = 97
-->{Name:王3 Age:97}
[{王1 99} {王2 98} {王3 97}]
酸爽!