PythonがApp EngineでサポートするExpandoモデルのようなことをしたいのですが。
事前にプロパティを宣言したくない場合があります。特別なモデルサブクラスであるExpandoは、エンティティの動作を変更して、割り当てられた属性が(アンダースコアで始まらない限り)データストアに保存されるようにします。
Goでこれを行うにはどうすればよいですか?
事前に注意してください:
2つのAPIがあります。インポートパスappengine/datastore
を持つものは、引数としてチャネルを使用します。インポートパスgoogle.golang.org/appengine/datastore
を持つもう1つはスライスを使用します。以下の例をあなたのケースに合わせて調整してください。詳細については、この質問を参照してください:Golang appengineを正しくインポートするにはどうすればよいですか?
動的プロパティを持つエンティティの鍵は、PropertyLoadSaver
インターフェースです。このインターフェースを実装することで、保存時に、保存するエンティティのプロパティを動的に構築できます。
また、これを自分で行う必要がないように、Go AppEngineプラットフォームは、PropertyList
基本的にプロパティのリスト(スライス)であるタイプを提供し、Property
それも実装しPropertyLoadSaver
ます。
したがって、GoのExpandoモデルはPropertyList
です。エンティティに必要なプロパティを追加し、このPropertyList
値を保存するだけです。
次に例を示します。
c := appengine.NewContext(r)
props := datastore.PropertyList{
datastore.Property{Name: "time", Value: time.Now()},
datastore.Property{Name: "email", Value: "[email protected]"},
}
k := datastore.NewIncompleteKey(c, "DynEntity", nil)
key, err := datastore.Put(c, k, &props)
c.Infof("%v %v", key, err)
この例では、およびの"DynEntity"
2つの動的プロパティで名前が付けられたエンティティを保存します。"time"
"email"
通りPropertyList
のタイプがスライスである、あなたはまた、組み込みの使用することができますappend()
あなたも初期化することができるように、それにプロパティを追加する機能をprops
次のように:
var props datastore.PropertyList
props = append(props, datastore.Property{Name:"time", Value: time.Now()})
props = append(props, datastore.Property{Name:"email", Value: "[email protected]"})
map
動的エンティティに変えるPropertyLoadSaver
インターフェイスは、我々はそれを自分自身を実装することができ、複雑ではありません。次の例では、シンプルなカスタムタイプに実装しますmap
。
type DynEnt map[string]interface{}
func (d *DynEnt) Load(props []datastore.Property) error {
// Note: you might want to clear current values from the map or create a new map
for _, p := range props {
(*d)[p.Name] = p.Value
}
return nil
}
func (d *DynEnt) Save() (props []datastore.Property, err error) {
for k, v := range *d {
props = append(props, datastore.Property{Name: k, Value: v})
}
return
}
以下は、スライスの代わりにチャネルを使用した「古い」インターフェースでの実装の様子です。
type DynEnt map[string]interface{}
func (d *DynEnt) Load(ch <-chan datastore.Property) error {
// Note: you might want to clear current values from the map or create a new map
for p := range ch { // Read until channel is closed
(*d)[p.Name] = p.Value
}
return nil
}
func (d *DynEnt) Save(ch chan<- datastore.Property) error {
defer close(ch) // Channel must be closed
for k, v := range *d {
ch <- datastore.Property{Name: k, Value: v}
}
return nil
}
今、我々は使用することができるDynEnt
だけで行くの他のマップなどの種類を、その実装しているのでPropertyLoadSaver
、それはエンティティとして保存することができます(と任意のエンティティがそれにロードすることができます):
c := appengine.NewContext(r)
d := DynEnt{"email": "[email protected]", "time": time.Now()}
k := datastore.NewIncompleteKey(c, "DynEntity", nil)
key, err := datastore.Put(c, k, &d)
c.Infof("%v %v", key, err)
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加