猿问

使用反射和动态类型附加到 go lang 切片

,有一个给定的结构(Foo)。我发现这个概念很有趣,并且想知道对于动态类型也可以这样做。


给定以下动态结构(完美运行),您如何创建切片并附加到它?


在这里查看我的尝试:


在这个片段中,我创建了动态类型。这工作正常。



        typeString := reflect.TypeOf("")

        typeInteger := reflect.TypeOf(0)

        fields := make(map[string]*reflect.StructField)

        fields["A"] = &reflect.StructField{

                Name: "A",

                Type: typeString,

                Tag:  reflect.StructTag(`json:"a"`),

        }

        fields["B"] = &reflect.StructField{

                Name: "B",

                Type: typeInteger,

                Tag:  reflect.StructTag(`json:"b"`),

        }

        var structFields []reflect.StructField

        for _, v := range fields {

                structFields = append(structFields, *v)

        }


        structType := reflect.StructOf(structFields)

使用该结构,我们看到它工作正常:


        v := reflect.New(structType)

        v.Elem().FieldByName("A").SetString("qwer")

        v.Elem().FieldByName("B").SetInt(123)


        v2 := reflect.New(structType)

        v2.Elem().FieldByName("A").SetString("asdf")

        v2.Elem().FieldByName("B").SetInt(456)


        //+ these look good

        fmt.Printf("%v\n", v)

        fmt.Printf("%v\n", v2)

然而,进入动态切片,我们得到一个错误:


        reflection := reflect.MakeSlice(reflect.SliceOf(reflect.TypeOf(structType).Elem()), 0, 0)


        reflectionValue := reflect.New(reflection.Type())

        reflectionValue.Elem().Set(reflection)


        slicePtr := reflect.ValueOf(reflectionValue.Interface())


        sliceValuePtr := slicePtr.Elem()


        value := v.Elem()


        // ERROR HERE

        toSet := reflect.Append(sliceValuePtr, value)

需要调整什么以使所有内容都对齐并且Append?


在操场上查看以下内容:


https://play.golang.org/p/Vrx7FTlVBp9


千万里不及你
浏览 166回答 2
2回答

千巷猫影

值为structTypea reflect.Type。该表达式reflect.TypeOf(structType)计算reflect.Typefor reflect.Type。直接使用structType而不是调用reflect.TypeOf(structType).typeString := reflect.TypeOf("")typeInteger := reflect.TypeOf(0)fields := make(map[string]*reflect.StructField)fields["A"] = &reflect.StructField{    Name: "A",    Type: typeString,    Tag:  reflect.StructTag(`json:"a"`),}fields["B"] = &reflect.StructField{    Name: "B",    Type: typeInteger,    Tag:  reflect.StructTag(`json:"b"`),}var structFields []reflect.StructFieldfor _, v := range fields {    structFields = append(structFields, *v)}structType := reflect.StructOf(structFields)v := reflect.New(structType)v.Elem().FieldByName("A").SetString("qwer")v.Elem().FieldByName("B").SetInt(123)v2 := reflect.New(structType)v2.Elem().FieldByName("A").SetString("asdf")v2.Elem().FieldByName("B").SetInt(456)//+ these look goodfmt.Printf("%v\n", v)fmt.Printf("%v\n", v2)reflection := reflect.MakeSlice(reflect.SliceOf(structType), 0, 0)fmt.Printf("typeof structType: %v\n", structType)fmt.Printf("typeof structType | elem: %v\n", reflect.TypeOf(structType).Elem())reflectionValue := reflect.New(reflection.Type())reflectionValue.Elem().Set(reflection)slicePtr := reflect.ValueOf(reflectionValue.Interface())sliceValuePtr := slicePtr.Elem()value := v.Elem()fmt.Printf("value: %T = (%v)\n", value, value)fmt.Printf("slice: %T = (%v)\n", sliceValuePtr, sliceValuePtr)toSet := reflect.Append(sliceValuePtr, value)fmt.Printf("toSet: %T = (%v)\n", toSet, toSet)sliceValuePtr.Set(toSet)result := sliceValuePtr.Interface()fmt.Printf("result: %T = (%v)\n", result, result)在 Go 操场上运行它。这是代码的简化版本:stringType := reflect.TypeOf("")intType := reflect.TypeOf(0)t := reflect.StructOf([]reflect.StructField{    {        Name: "A",        Type: stringType,        Tag:  reflect.StructTag(`json:"a"`),    },    {        Name: "B",        Type: intType,        Tag:  reflect.StructTag(`json:"b"`),    },})v1 := reflect.New(t).Elem()v1.FieldByName("A").SetString("qwer")v1.FieldByName("B").SetInt(123)v2 := reflect.New(t).Elem()v2.FieldByName("A").SetString("asdf")v2.FieldByName("B").SetInt(456)slice := reflect.MakeSlice(reflect.SliceOf(t), 0, 0)slice = reflect.Append(slice, v1, v2)fmt.Printf("result: %s = (%v)\n", slice.Type(), slice)

SMILET

如您所知,reflect.TypeOf返回传递给它的值的类型的reflect.Type表示。因此,如果您有一个值,例如,其类型为并且您将其传递给,则返回的将是该值所表示的类型的表示,而不是该类型的表示。structType reflect.Typereflect.TypeOfreflect.Typereflect.TypestructType把事情简单化。slice := reflect.MakeSlice(reflect.SliceOf(structType), 0, 0)slice = reflect.Append(slice, v.Elem())slice = reflect.Append(slice, v2.Elem())https://play.golang.org/p/p_3TI0gdvHl
随时随地看视频慕课网APP

相关分类

Go
我要回答