post Image
DatastoreからGetした時に余計なPropertyがある場合エラーになるが無視してもいい

タイトルのまんまです。

話の前提として、以下のパッケージを使っているものとします。

google.golang.org/appengine/datastore

SDK組み込みの appengine/datastore や Cloud Datastore用の cloud.google.com/go/datastore については言及しませんが、多分似たような設計になってると思うので流用可能なテクではないでしょうか。

モチベーション

GAE/J+Slim3とかだとKindのSchemaの変更は大変気軽にできました。
新規追加のプロパティはデフォルト値になりますし、削除したプロパティはインスタンスに変換される時に無視されるからです。

一方、Goは違います。
Entityに存在するプロパティに対応するフィールドがstructにないと、エラーになります。
このため、GAE/Goでは不要になったプロパティを削除できず、ずっと残す運用をしていました。
具体的に以下のような感じです。

type Sample struct {
    ID     int64  `goon:"id" datastore:"-"`
    Name   string
}

これを以下のように変更して適当に検索かけて使ってるところ消す。

type Sample struct {
    ID               int64   `goon:"id" datastore:"-"`
    DeprecatedName   string  `datastore:"Name"`
}

もしくは、 datastore.PropertyLoadSavor を使って読み出し時に該当のプロパティを抜いてから変換します。
Goの場合 ps = ps.Filter(p => p.Name != "Name") みたいなコードが書きづらいのでひたすらめんどくさいです。

何も考えずにプロパティ削りたい。

対応

structに対し、 datastore.PropertyLoadSavor を実装します。
まずは今まで書いていたであろう実装を示しておきます。

func (entity *Foo) Load(p []datastore.Property) error {
    if err := datastore.LoadStruct(entity, p); err != nil {
        return err
    }

    // 何かやったりする

    return nil
}

func (entity *Foo) Save() ([]datastore.Property, error) {
    // 何かやったりする

    p, err := datastore.SaveStruct(entity)
    if err != nil {
        return nil, err
    }
    return p, nil
}

これを以下のように変更します。

func (entity *Foo) Load(p []datastore.Property) error {
    err := datastore.LoadStruct(entity, p)
    if fmerr, ok := err.(*datastore.ErrFieldMismatch); ok && fmerr != nil && fmerr.Reason == "no such struct field" {
        // ignore
    } else if err != nil {
        return err
    }

    // 何かやったりする

    return nil
}

func (entity *Foo) Save() ([]datastore.Property, error) {
    // 何かやったりする

    p, err := datastore.SaveStruct(entity)
    if err != nil {
        return nil, err
    }
    return p, nil
}

これだけでOKです。

これで大丈夫な理由

このへん

We don’t return early, as we try to load as many properties as possible.
It is valid to load an entity into a struct that cannot fully represent it.
That case returns an error, but the caller is free to ignore it.

要するに、 datastore.LoadStruct した時に *datastore.ErrFieldMismatch が返ってきても途中で処理打ち切ったりせずにお尻まで処理してからエラー返してるので無視してもデータが壊れてることはないゾ!という話。

Reasonの値をチェックしているのは若干神経質な気もするので、おおらかな性格の人はReasonはみなくても多分大丈夫なんじゃないでしょうか。

感想

無視するために独自の datastore.LoadStruct 実装しなきゃかなと思って結構手を動かしてたんだけどある時 datastore.ErrFieldMismatch の存在とソレに関わる処理を見つけて無駄な作業だった事を知ってしまいたいへん悲しい(有益な発見

とりあえず、これから本番環境に突っ込んでみる予定です。


『 Go 』Article List
Category List

Eye Catch Image
Read More

Androidに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

AWSに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Bitcoinに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

CentOSに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

dockerに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

GitHubに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Goに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Javaに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

JavaScriptに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Laravelに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Pythonに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Rubyに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Scalaに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Swiftに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Unityに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Vue.jsに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Wordpressに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

機械学習に関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。