[英]Dynamically create protocol buffer object
我正在使用一組協議緩沖區,我無法理解我需要做什么來實例化它們,並且必須在運行時計算它。 我知道我需要以某種方式使用reflect
來執行此操作,但似乎沒有任何效果。 在編譯時,我只知道我需要創建的第一個協議緩沖區。 該緩沖區包含一個字段,告訴我下一個我需要創建的 integer id。
我所有的緩沖區都在名為kpb
的 package 中定義。
我發現第一個是這樣的:
info := &kpb.ArchiveInfo{}
err := proto.Unmarshal(<byte array>, info)
// error handling
messageType = *info.MessageType // 1
我有一個 map 定義了我需要調用的下一個緩沖區。 map 定義如下:
請注意,此 map 的所有值都是proto.ProtoMessage
對象,但使用它似乎導致的問題多於解決的問題。
var registryMap = map[uint32]interface{}{
1: &kpb.KNDocumentArchive{},
...etc
}
所以當我引用這個 map 時,我是這樣做的:
var klass interface{}
//stuff
klass = registryMap[messageType]
fmt.Println(klass) // *kpb.KNDocumentArchive
但是,我想不通的是如何用正確的類型實例化一個變量來解組我擁有的有效負載。
我可以通過執行以下操作獲取klass
的type
:
klassType := reflect.TypeOf(klass)
fmt.Println(klassType) // kpb.KNDocumentArchive - as expected
但是,如果我嘗試用它創建一個新變量,我會得到一個錯誤
payloadObj := new(klass)
// klassType (variable of type reflect.Type) is not a type
因此,即使類型是我期望的kpb.KNDocumentArchive
,它仍然以某種方式reflect.Type
當我使用proto.ProtoMessage
作為 map 返回的類型時,我可以通過這部分並實例化變量,但我無法將其傳遞給proto.Unmarshal
,因為它正確地期望類型為kpb.KNDocumentArchive
我在這里做錯了什么?
我能夠弄清楚這一點。 我需要使用 proto 內置功能。 最終結果是將我的 map 更新為:
var registryMap = map[uint32]string{
1: "KN.KNDocumentArchive",
}
然后解組部分就這樣解決了:
func GetProto(id uint32, messageBytes []byte) proto.Message {
klass := registryMap[id]
if klass == "" {
panic("Don't know how to parse Protobuf message type " + fmt.Sprint(id))
}
messageName := protoreflect.FullName(klass)
pbtype, err := protoregistry.GlobalTypes.FindMessageByName(messageName)
if err != nil {
panic(err)
}
msg := pbtype.New().Interface()
err = proto.Unmarshal(messageBytes, msg)
if err != nil {
panic(err)
}
return msg
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.