在golang中使用反射通用修改结构字段

cld4siwp  于 2023-01-28  发布在  Go
关注(0)|答案(1)|浏览(125)

下面是一个使用reflect包来修改结构体字段的方法,它适用于特定的结构体类型

func modify(obj Car) interface{} {
        ty := reflect.TypeOf(obj)
        for i := 0; i < ty.NumField(); i++ {
            rval := reflect.Indirect(reflect.ValueOf(&obj))
            field := rval.Field(i)
            fieldType := field.Kind()
    
            switch fieldType {
            case reflect.String:
                field.SetString("")
            case reflect.Int:
                field.SetInt(0)
            case reflect.Ptr:
                field.Set(reflect.ValueOf(nil))
    
            }
        }
        return obj
    }

修改签名以

func modify(obj interface{}) interface{} {

导致恐慌:reflect:调用接口Value上的reflect.Value.Field
在线

field := rval.Field(i)

https://go.dev/play/p/pGfKtIg5RUp它与签名一起使用

func modify(obj Car) interface{} {

https://go.dev/play/p/31Oh6WLmlGP
为什么编译时类型要修改行为?这里的目标是基于struct标记屏蔽某些字段。它可以 Package 一个端点,而被 Package 的方法的输入和输出可以是struct或指针,所以在上面的情况下,两个调用都应该工作

modify(car)

modify(&car)
vulvrdjw

vulvrdjw1#

这是它对值类型和指针类型的工作方式

func modify(obj interface{}) interface{} {
    rv := reflect.ValueOf(obj)
    trv := reflect.TypeOf(obj)
    value := reflect.New(rv.Type())
    if rv.Kind() == reflect.Pointer {
        rv = reflect.ValueOf(obj).Elem()
        trv = reflect.TypeOf(obj).Elem()
        value = reflect.New(rv.Type())
    }
    for i := 0; i < rv.NumField(); i++ {
        field := rv.Field(i)
        fieldType := field.Kind()
        v := value.Elem().Field(i)
        tag, _ := trv.Field(i).Tag.Lookup("es")
        if len(tag) != 0 {

            switch fieldType {
            case reflect.String:
                v.SetString(tag)
            case reflect.Int:
                v.SetInt(0)
            case reflect.Ptr:
                v.Set(reflect.ValueOf(nil))

            }
        } else {
            v.Set(field)
        }
    }

    return value
}

https://go.dev/play/p/C1pqw_UbPcG

相关问题