2016-04-26 93 views
0

我爲Golang使用Protobuf。 Protobuf生成類型指針實現的消息類型proto.Message()。 例如將盒裝結構轉換爲盒裝指針 - golang

func (*SomeMessage) Message() {} 

的protobuf的lib中有像Marshal(proto.Message)

現在我的實際問題的方法。

message := SomeMessage {} 
SendMessage(&message) 

func SendMessage(message interface{}) { 
    switch msg := message.(type) { 
     case proto.Message: 
      //send across the wire or whatever 
     default: 
      //non proto message, panic or whatever 
    } 
} 

上述工作正常。 但是,如果我不將消息作爲指針傳遞,那麼SendMessage中的代碼將不匹配,因爲接口只在SomeMessage指針上實現,而不是在值上實現。

我想要做的是:

message := SomeMessage {} 
SendMessage(message) //pass by value 
//there are more stuff going on in my real code, but just trying to show the relevant parts 

func SendMessage(message interface{}) { 
    //match both pointer and value as proto.Message 
    //and then turn the value into a pointer so that 
    //other funcs or protobuf can consume it 

    message = MagicallyTurnBoxedValueIntoBoxedStruct(message)  

    switch msg := message.(type) { 
     case proto.Message: 
      //send across the wire or whatever 
     default: 
      //non proto message, panic or whatever 
    } 
} 

最好,我想能夠通過既作爲指針和值。 爲什麼我想按值傳遞的原因是,這可以作爲一個貧窮的芒隔離傳遞消息,當跨越夠程/線程等 (在缺乏不變性)

所有這一切,如果很可能避免採取行動protobuf生成器生成的允許值也被視爲proto.Message()。 或者如果有更好的方法來做不可變的消息。

這不是超級重要的,如果可能的話,冷靜,如果它不是,MEH :-)

[編輯]

如果我有消息的reflect.Type和的reflect.Type消息的指針類型。 是否可以通過某種方式創建指向使用「反射」值的指針類型實例?

回答

1

通常情況下,您無法獲取值的地址,這意味着您無法簡單地將接口轉換爲滿足Protobuf要求的指針。這就是說,你可以動態地創建一個新的指針,然後將值複製到那個值,然後將新分配的指針傳遞給protobuf。

下面是一個example on Play

價值 - >指針轉換:

func mkPointer(i interface{}) interface{} { 
    val := reflect.ValueOf(i) 
    if val.Kind() == reflect.Ptr { 
     return i 
    } 
    if val.CanAddr() { 
     return val.Addr().Interface() 
    } 
    nv := reflect.New(reflect.TypeOf(i)) 
    nv.Elem().Set(val) 
    return nv.Interface() 
} 
  • 我們先看看它的指針,如果是的話,只返回值。
  • 然後我們檢查它是否可尋址並返回。
  • 最後,我們創建一個新類型的實例並將其內容複製並返回。

既然這樣複製數據,它可能不適合您的目的。它將全部取決於消息的大小和期望的調用速率與一個值(因爲這將產生更多的垃圾)。

+0

工作,謝謝! –

+0

@RogerAlsing我想指出的是,雖然這樣做會很慢並且過度設計,不應該用於任何實際項目。 – OneOfOne

+0

是的,我明白了,最好的解決方案是讓protoc生成不可變的結構。但是看到它是可能的,仍然很有趣。 –