根
実際、言及された記事は
github.com/golang/protobuf/{proto,protoc-gen-go}
      
      パッケージについて話していました。 それらの何が問題になっていますか? つまり、その反射が使用されます。 特定の構造セットで機能するプロジェクトがあるとします。 そして、これらの構造はプロトコルバッファに常にエンコードされ、その逆も同様です。 常に異なる、予測不可能なタイプであれば、問題はありません。 ただし、セットが事前にわかっている場合は、リフレクションを使用する必要はありません。 ご存知のように、コーディングを担当するインターフェースを使用するのが慣例です。 これは
encoding/json
      
      例です:
 type Marshaler interface { MarshalJSON() ([]byte, error) } type Unmarshaler interface { UnmarshalJSON([]byte) error }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      参照: マーシャラー 、 アン マーシャラー
エンコーダーがこれらのインターフェイスの1つを具体化する型に遭遇した場合、この場合、すべての作業はメソッドに依存します。
  簡単なJSONの例 
        
        
        
      
常に
        
        
        
      
    
        
        
        
      
      
        
        
        
      
はとてもバラ色ではありません。 たとえば、 yaml( Eng。 )について読むべきことがあります。一般的にはこのトピックについてです。
        
        
        
      
    
       type X struct { Name string, Value int, } func (x *X) MarshalJSON() ([]byte, error) { return []byte(fmt.Sprintf(`{"name": %q, "value": %d}`, x.Name, x.Value)) }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      常に
(Un)Marshaler
      
      はとてもバラ色ではありません。 たとえば、 yaml( Eng。 )について読むべきことがあります。一般的にはこのトピックについてです。
キー
いつものように、解決策は簡単です。 別のパッケージを使用:
 go get github.com/gogo/protobuf/{proto,protoc-gen-gogo,gogoproto,protoc-gen-gofast}
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      これらのパッケージは、単に利便性と速度を追加します。
パッケージについて(リンク):
ご覧のとおり、1.10x以上の加速。 拡張機能のセットを単純に使用することができます-加速なし。 単にスピードアップする機会があります。 私はこのコマンドで解決しました:
 protoc \ --proto_path=$GOPATH/src:$GOPATH/src/github.com/gogo/protobuf/protobuf:. \ --gogofast_out=. *.proto
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      拡張機能(ある場合)とアクセラレーションの両方を取得します。 
        例 
       拡張機能を使用するように呼び出すのではなく、参照用です。 
      
        
        
        
      
    
        
        
        
      
成功します
        
        
        
      
    
        
        
        
      
    
 syntax="proto3"; package some; //protoc \ // --proto_path=$GOPATH/src:$GOPATH/src/github.com/gogo/protobuf/protobuf:. \ // --gogofast_out=. *.proto import "github.com/gogo/protobuf/gogoproto/gogo.proto"; //  ,   Equal,   option (gogoproto.equal_all) = true; option (gogoproto.goproto_stringer_all) = false; // Stringer   (    ) option (gogoproto.stringer_all) = true; //   -    option (gogoproto.populate_all) = true; //    option (gogoproto.testgen_all) = true; //   option (gogoproto.benchgen_all) = true; //  option (gogoproto.marshaler_all) = true; //   option (gogoproto.sizer_all) = true; //  option (gogoproto.unmarshaler_all) = true; // enums,   -    option (gogoproto.goproto_enum_prefix_all) = false; enum Bool { Yes = 0; No = 1; DontCare = 2; } message Some { option (gogoproto.goproto_unrecognized ) = false; option (gogoproto.goproto_getters) = false; Bool Waht = 1; int64 Count = 2; bytes Hash = 3; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      成功します
 /*        (Size, String  ..)       */ type Bool int32 const ( Yes Bool = 0 No Bool = 1 DontCare Bool = 2 ) // ... type Some struct { Waht Bool `protobuf:"varint,1,opt,name=Waht,proto3,enum=some.Bool" json:"Waht,omitempty"` Count int64 `protobuf:"varint,2,opt,name=Count,proto3" json:"Count,omitempty"` Hash []byte `protobuf:"bytes,3,opt,name=Hash,proto3" json:"Hash,omitempty"` } //   proto.Message (github.com/golang/protobuf/proto) func (m *Some) Reset() { *m = Some{} } func (*Some) ProtoMessage() {} //   func (m *Some) Marshal() (data []byte, err error) { // ... } //   func (m *Some) Unmarshal(data []byte) error { // ... }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      ご覧のとおり、一部の拡張機能にはベータ版のステータスがあり、これはproto3に関する注意事項です。 heしないでください。 このパッケージは、多くの人によって正常に使用されています(ホームページを参照)。 それでも、これはテストの作成を免除するものではありません。 拡張機能やものに興味がない場合は、プロジェクトのREADMEに記載されているように、このコマンドで十分です。
 protoc --gofast_out=. myproto.proto
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      ストーンズ
軟膏で飛ぶ
以前のスポイラーを調べなかった場合、その断片の1つを強調したいと思います。
 func (m *Some) Reset() { *m = Some{} } //  
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      実際のところ、
gogo
      
      使用すると「高速」構造を生成できます。 「古い」
github.com/golang/protobuf/proto
      
      それらを使用することもできます。 この場合、
Marshal
      
      および
Unmarshal
      
      方法が使用されます-問題はありません。 しかし、構造の同じインスタンスを何度も使用するとどうなりますか。 構造が大きい場合(いいえ、巨大な場合)、プールを使用して "ワークアウトされた"構造を保存し、それらを元に戻して再利用しても大丈夫です。
github.com/golang/protobuf/proto
      
      アプローチ。 参照先
 func Unmarshal(buf []byte, pb Message) error { pb.Reset() //    return UnmarshalMerge(buf, pb) }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      Reset
      
      呼び出します。 したがって、
*m = Some{}
      
      -古い構造は破棄され、新しい構造が作成されます。 この構造は小さい-気にしない-しかし、大きなハッシュが使用される場合に備えて、
Hash []byte
      
      (
Hash []byte
      
      、 割り当てられたメモリ )を保存したいと思います。
github.com/gogo/protobuf/proto
      
      アプローチは、コピー
github.com/gogo/protobuf/proto
      
      ペーストに似ています。 一見ではありません。
じゃあ
Unmarshal
      
      メソッドを直接使用するか、
Unmarshal
      
      を試すことができます
MyReset
      
      メソッドを追加し、スライスの長さをカットします-容量を残します。 いや! 生成された
Unmarshal
      
      行は次の
Unmarshal
      
      です。
 m.Hash = append([]byte{}, data[iNdEx:postIndex]...)
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      新しいスライスが作成されます-古いスライスがGCファイアボックスに飛び込みます。 実際、小さな構造物(構造物のフィールド-そしてすべて一緒に )がある場合、最も簡単な方法は入浴しないことです。 大規模な場合-回避策を探します(生成されたコードを書き換えてください)。 現在の実装では、プールを使用しても意味がありません。
ボーナス
ライブラリはストリーミングに便利です。
io.Writer
      
      からの読み取り、
io.Writer
      
      でのメッセージの書き込み-このような自転車はすでに存在します。
json
      
      についての会話が来てから: github.com/pquerna/ffjson jsonについても同様です。 単なるジェネレーターではなく、
json
      
      +
Go
      
      用のスイス製ナイフです。
私が速度とプールについて話し始めたので: github.com/valyala/fasthttp 。
net/http
      
      「クイック」置換。 メモリの再利用による加速。 追加機能も同じです。