在protobuf文件中使用google.protobuf.Value,在结构中使用go接口{}字段,反之亦然

在protobuf文件中使用google.protobuf.Value,在结构中使用go接口{}字段,反之亦然,go,reflection,type-conversion,protocol-buffers,grpc,Go,Reflection,Type Conversion,Protocol Buffers,Grpc,我有一个protobuf消息,它看起来像这样: // Rule : Includes an entity , an operation and a comparison value message Rule { string entity = 1; string operator = 2; google.protobuf.Value value = 3; } 我在这里使用Value,因为Value可以是任何类型 在我使用生成代码的Golang代码中: type Rule struc

我有一个protobuf消息,它看起来像这样:

// Rule : Includes an entity , an operation and a comparison value
message Rule {
  string entity = 1;
  string operator = 2;
  google.protobuf.Value value = 3;
}
我在这里使用Value,因为Value可以是任何类型

在我使用生成代码的Golang代码中:

type Rule struct {
 Entity string
 Operator string
 Value interface{}
}
现在,我的问题是: 如何将google.protobuf.Value类型(nil、number、string、bool、struct、list)表示的类型转换为接口{} 并在运行时将接口{}的动态类型转换回google.protobuf.Value类型


我真的需要一些帮助,在这里找到了一个排序解决方案(),但我希望有一个更简单的方法来实现这一点。

为了完整起见,请评论:

func convertToValue(v interface{}, from reflect.Type) (*types.Value, error) {
    switch from.Kind() {
    case reflect.String:
        if reflect.ValueOf(v).String() == "true" || reflect.ValueOf(v).String() == "false" {
            boolVal, err := strconv.ParseBool(reflect.ValueOf(v).String())
            if err != nil {
                return nil, err
            }
            return &types.Value{Kind:&types.Value_BoolValue{BoolValue:boolVal}}, nil
        }
        return &types.Value{Kind:&types.Value_StringValue{StringValue:reflect.ValueOf(v).String()}}, nil
    case reflect.Int64:
    case reflect.Float64:
        return &types.Value{Kind:&types.Value_NumberValue{NumberValue:reflect.ValueOf(v).Float()}}, nil
    case reflect.Slice:
        list := reflect.ValueOf(v)
        outputList := make([]*types.Value,0)
        for i:=0 ; i < list.Len(); i++ {
            val, err := convertToValue(list.Index(i).Interface(), reflect.TypeOf(list.Index(i).Interface()))
            if err != nil {
                return nil, err
            }
            outputList = append(outputList, val)
        }
        return &types.Value{Kind:&types.Value_ListValue{ListValue:&types.ListValue{Values:outputList}}}, nil
    case reflect.Struct:
        valStruct := reflect.ValueOf(v)
        outputMap := make(map[string]*types.Value)
        numOfField := valStruct.NumField()
        for i := 0; i < numOfField; i++ {
            val, err := convertToValue(valStruct.Field(i).Interface(), reflect.TypeOf(valStruct.Field(i).Interface()))
            if err != nil {
                return nil, err
            }
            outputMap[valStruct.Field(i).Type().Name()] = val
        }

        return &types.Value{Kind:&types.Value_StructValue{StructValue:&types.Struct{Fields:outputMap}}}, nil
    default:
        return nil, nil
}

```//字符串类型,如果from.Kind()==reflect.String&&(reflect.ValueOf(v).String()==“true”| | | reflect.ValueOf(v).String()==“false”){boolVal,err:=strconv.ParseBool(reflect.ValueOf(v.String())如果err!=nil{return nil,err}return&types.Value{Kind:&types.Value_BoolValue{BoolValue:boolVal}},nil}``是死代码。
func convertValueToInterface(value types.Value) (interface{}, error) {

    switch {
    case _ , ok := value.Kind.(*types.Value_NullValue); ok:
        return nil, nil
    case x , ok := value.Kind.(*types.Value_StringValue); ok:
        return x.StringValue, nil
    case x , ok := value.Kind.(*types.Value_NumberValue); ok:
        return x.NumberValue, nil
    case x , ok := value.Kind.(*types.Value_BoolValue); ok:
        return strconv.FormatBool(x.BoolValue), nil
    case x , ok := value.Kind.(*types.Value_ListValue); ok:
        if x == nil || x.ListValue == nil || x.ListValue.Values == nil {
            return nil, nil
        }
        listValue := x.ListValue.Values
        if len(listValue) == 0 {
            return nil, nil
        }
        val, err := convertValueToInterface(*listValue[0])
        if err != nil {
            return nil, err
        }
        typ := reflect.TypeOf(val)
        outputList := reflect.MakeSlice(reflect.SliceOf(typ),0,0)
        for _, value := range listValue {
            if value != nil {
                val, err := convertValueToInterface(*value)
                if err != nil {
                    return nil, err
                }
                outputList = reflect.Append(outputList, reflect.ValueOf(val))
            }
        }
        return outputList.Interface(), nil
    case x , ok := value.Kind.(*types.Value_StructValue); ok:
        if x == nil || x.StructValue == nil || x.StructValue.Fields == nil {
            return nil, nil
        }
        mapValue := x.StructValue.Fields
        var keyTyp reflect.Type
        var typ reflect.Type
        for key,value := range mapValue {
            if value != nil {
                val, err := convertValueToInterface(*value)
                if err != nil {
                    return nil, err
                }
                keyTyp = reflect.TypeOf(key)
                typ = reflect.TypeOf(val)
                break
            } else {
                return nil, nil
            }
        }
        outputMap := reflect.MakeMap(reflect.MapOf(keyTyp, typ))
        for key,value := range mapValue {
            if value != nil {
                val, err := convertValueToInterface(*value)
                if err != nil {
                    return nil, err
                }
                outputMap.SetMapIndex(reflect.ValueOf(key), reflect.ValueOf(val))
            }
        }
        return outputMap.Interface(), nil
    default:
        return nil, nil
}