反射三部曲3·go反射实现眼熟的UnMarshal操作

作者原创,一字一句手打,全程代码干货。如有帮助,欢迎留下足迹哦!

目录

背景

基本准备

UnMarshal的核心逻辑


 

背景

代码写的手麻了,在休息的时候突然想到一些场景,就想到了平时常见的各种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}]

酸爽!

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ProblemTerminator

您的鼓励将是作者最大的动力哦!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值