根
実際、言及された記事は
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
「クイック」置換。 メモリの再利用による加速。 追加機能も同じです。