当前位置: > > > > 在结构体中使用带有 go interface{} 字段的 protobuf 文件中的 google.protobuf.Value ,反之亦然
来源:stackoverflow
2024-04-26 17:18:34
0浏览
收藏
目前上已经有很多关于Golang的文章了,自己在初次阅读这些文章中,也见识到了很多学习思路;那么本文《在结构体中使用带有 go interface{} 字段的 protobuf 文件中的 google.protobuf.Value ,反之亦然》,也希望能帮助到大家,如果阅读完后真的对你学习Golang有帮助,欢迎动动手指,评论留言并分享~
问题内容
我有 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{} }
现在,我的问题是: 如何将 kind of google.protobuf.value (nil, number, string, bool, struct, list) 表示的类型转换为 interface{} 并在运行时将接口的动态类型转换回 google.protobuf.value 类型?
我确实需要一些帮助,在这里找到了一种解决方案(https://go.googlesource.com/protobuf/+/4c057caa84dc5e1bc6bf0d9fe8af9180a6151e07/internal/value/convert.go),但希望有一种更简单的方法关于这个。
解决方案
为了完整性而发表评论:
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 }
和
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 }
今天关于《在结构体中使用带有 go interface{} 字段的 protobuf 文件中的 google.protobuf.Value ,反之亦然》的内容就介绍到这里了,是不是学起来一目了然!想要了解更多关于的内容请关注公众号!