2016-04-26 34 views
0

私はGolangにProtobufを使用しています。 Protobufは、タイプポインタがproto.Message()を実装するメッセージタイプを生成します。例: boxed構造体をboxedポインタにキャスト - golang

func (*SomeMessage) Message() {} 

いるProtobuf libには、私の実際の問題に今Marshal(proto.Message)

のようなメソッドを持っています。

上記の動作は問題ありません。 しかし、メッセージをポインタとして渡さないと、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()としても扱うように生成しました。 または不変のメッセージを行うためのより良い方法があれば。

その可能ならばそのない場合、私はメッセージのreflect.Typeとのreflect.Typeを持っている場合は、[EDIT]

:-) MEH、、、、

クールスーパー重要ではありませんメッセージのポインタ型。 "reflect"を使用して値を指すポインタ型のインスタンスを作成することは、どういうわけかできますか?

答えて

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を持っているだろうが、それは可能だったことを見て興味深かったです。 –

関連する問題