golang 动态结构体

背景

语言: golang

目前项目允许业务自定自己业务下私有字段。 造成同一类型实例数据,在不同的业务下字段是不一样。 在实际处理中无法使用struct来定义。 当实例数据在不同服务之间数据传递, 只能用key-val结构(map[string]interface{})来描述,在实际处理中非常不变, 需要大量判断数据类型和类型转换代码,整体使用起来比较麻烦。

eg:


    inst := make(map[string]interface{},0)
    err := json.Unmarshal([]byte(....), &inst)
    if err != nil {
        return 
    }
    var name string 
    if iName := inst["name"]; iName != nil {
        id, ok := inst["id"].(string)
        if !ok {
           return errors.New("invalid")
        }
    }
   


如何解决大量类型转换和判断数据类型这个问题?

struct 在我们使用的时候之所以方便,简洁就是在做反序列的时候根据结构的定义字段和类型。 因此在使用的可以不用在做类型判断和数据校验 如果可以做一个dynamic struct,这个struct字段是根据执行逻辑动态调整字段和字段类型即可。

最终实现

最终的实现定一个DStruct 结构, 给DStruct结构实现基于byte stream json 反序列, 利用golang可以自定义struct UnmarshalJSON的特性, 当做json Unmarshal调用DStruct 根据用户定义的配置项目反序列化。 项目地址

eg:


 
	testStrJSONBytes := `{"int":1,"str":"str","bl":true, "arr_str":["1","2"],"arr_int":[1,2], "map":{"a":1,"b":64}, ` +
		`"test_struct":{"str":"string", "int":1},"interface":{"str":"string", "bl":true}}`
		// define a dynamic structure
	ds := &DStruct{}
	var i interface{}
	// define the fields of the dynamic structure
	ds.SetFields(map[string]reflect.Type{
		"int":         TypeInt,
		"str":         TypeString,
		"bl":          TypeBool,
		"arr_str":     TypeArrayStr,
		"arr_int":     TypeArrayInt,
		"map":         reflect.TypeOf(map[string]int64{}),
		"interface":   reflect.TypeOf(i),
	})
	// Unmarshal dynamic structure, you can directly use golang official
	err := json.Unmarshal([]byte(testStrJSONBytes), ds)
	if err != nil {
		t.Error(err.Error())
		return
	}
    intVal, err := ds.Int64("int")
    if err != nil {
		fmt.Error(err.Error())
		return
	}
		fmt.Println("int test, err: ", err, "val: ", intVal)
	str, err := ds.Str("str")
	if err != nil {
		fmt.Error(err.Error())
		return
	}
	fmt.Println("str test, err: ", err, "val: ", str)
	exists, err := ds.Value("interface", &i)
	if err != nil {
		fmt.Error(err.Error())
		return
	}
	fmt.Println("exist field: ", exists, "val: ", i)
articles from reage blog -- http://www.ireage.com