
【第10回】Go言語(Golang)入門~ObjectBox活用編~
2021.12.20
第10回~Go言語(Golang)入門~

(株)ライトコードの笹川(ささがわ)です!
今回は、前回に引き続き、ObjectBox を利用して、 「echo + ObjectBox」のREST APIを作ってみようと思います!
それでは、いってみましょう!
前回の記事はこちら
データ追加エンドポイントを実装してみよう
まずは、データの操作の前にテーブルの実装をします。
1 2 3 4 5 6 7 8 9 10 | package model //go:generate go run github.com/objectbox/objectbox-go/cmd/objectbox-gogen type Favorite struct { Id uint64 Name string Description string CreatedAt string } |
テーブルの構造体を記述したあとに、おまじないを実行します。
1 | go generate ./... |
これで、favorite.obx.go が作成されたら、テーブルデータの用意は完了です。
データベース接続&データ追加までの実装
それでは、前回同様に、データベースに接続してデータ追加までを実装します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | package main import ( "go_example/model" "net/http" "time" "github.com/labstack/echo" "github.com/objectbox/objectbox-go/objectbox" ) func main() { e := echo.New() e.POST("/add", addFavorite) e.Logger.Fatal(e.Start(":1323")) } func addFavorite(c echo.Context) error { favorite := new(AddFavoriteRequest) // データ受け取り if error := c.Bind(favorite); error != nil { return error } // initialize ob := initObjectBox() defer ob.Close() box := model.BoxForFavorite(ob) // データ追加 id, _ := box.Put(&model.Favorite{ Name: favorite.Name, Description: favorite.Description, CreatedAt: time.Now().String(), }) // 追加したデータを取得 result, _ := box.Get(id) // 追加したデータをレスポンスに渡す return c.JSON(http.StatusOK, result) } // AddFavoriteRequest データ追加リクエストのパース用構造体 type AddFavoriteRequest struct { Name string `json:"name"` Description string `json:"description"` } func initObjectBox() *objectbox.ObjectBox { objectBox, _ := objectbox.NewBuilder().Model(model.ObjectBoxModel()).Build() return objectBox } |
ObjectBox も echo も以前の記事で取り扱っているので、一つ一つの実装追加は省きます。
この形式でレスポンスが返ってきたら成功です。
1 2 3 4 5 6 | { "Id": 0, "Name": "hoge", "Description": "fuga", "CreatedAt": "1970-01-01 00:00:00 +0900" } |
確認
では、実行してみます!
1 | $ curl -X POST http://localhost:1323/add -H 'Content-Type: application/json' -d '{ "name": "猫" , "Description": "モフモフだから"}' |
結果はこちら。
1 2 3 4 5 6 | { "Id": 1, "Name": "猫", "Description": "モフモフだから", "CreatedAt": "2019-10-03 12:13:01.194436 +0900 JST m=+97.178858296" } |
CreatedAt が、Date型を気にせず文字列変換したため、分かりにくい表記になっていますが成功です!
修正
ちなみに、下記のようにすれば分かりやすくなります。
1 2 3 4 5 6 7 | const dateLayout = "2006/01/02 15:04:05" // データ追加 id, _ := box.Put(&model.Favorite{ Name: favorite.Name, Description: favorite.Description, CreatedAt: time.Now().Format(dateLayout), }) |
1 | "CreatedAt": "2019/10/03 12:24:47" |
dateLayout の中身が、よく分からない日付ですね(笑)
理由は、以下の記事に載っていますので、気になる方はご参考ください。
【参考記事】
https://qiita.com/ruiu/items/5936b4c3bd6eb487c182
データを検索してみよう
データの「Name」と「Description」の、それぞれと両方で検索ができるようにしてみます。
Name の検索を実装
まずは、「Name」の検索を実装します。
1 2 3 | func findName(box *model.FavoriteBox, name string) ([]*model.Favorite, error) { return box.Query(model.Favorite_.Name.Contains(name, true)).Find() } |
Descriptionの検索を実装
次に、「Description」の検索を実装します。
1 2 3 | func findDescription(box *model.FavoriteBox, description string) ([]*model.Favorite, error) { return box.Query(model.Favorite_.Description.Contains(description, true)).Find() } |
NameとDescription両方での検索の実装
最後に、「Name」と「Description」の両方での検索を実装します。
1 2 3 4 | func findKeyword(box *model.FavoriteBox, keyword string) ([]*model.Favorite, error) { return box.Query(objectbox.Any(model.Favorite_.Name.Contains(keyword, true), model.Favorite_.Description.Contains(keyword, true))).Find() } |
呼び出しを含めると、下記のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | package main import ( "go_example/model" "net/http" "time" "github.com/labstack/echo" "github.com/objectbox/objectbox-go/objectbox" ) func main() { e := echo.New() e.POST("/add", addFavorite) e.POST("/find", find) e.Logger.Fatal(e.Start(":1323")) } func find(c echo.Context) error { name := c.FormValue("name") description := c.FormValue("description") keyword := c.FormValue("keyword") // パラメーターなしの場合はエラーで返す if name == "" && description == "" && keyword == "" { return c.JSON(http.StatusNotFound, "param is not found") } // テーブル呼び出し box := getBox() // NameでLIKE検索 if name != "" { result, error := findName(box, name) if error != nil { return error } return c.JSON(http.StatusOK, result) } // DescriptionでLIKE検索 if description != "" { result, error := findDescription(box, description) if error != nil { return error } return c.JSON(http.StatusOK, result) } // Name,DescriptionでのLIKE検索 result, error := findKeyword(box, keyword) if error != nil { return error } return c.JSON(http.StatusOK, result) } func findName(box *model.FavoriteBox, name string) ([]*model.Favorite, error) { return box.Query(model.Favorite_.Name.Contains(name, true)).Find() } func findDescription(box *model.FavoriteBox, description string) ([]*model.Favorite, error) { return box.Query(model.Favorite_.Description.Contains(description, true)).Find() } func findKeyword(box *model.FavoriteBox, keyword string) ([]*model.Favorite, error) { return box.Query(objectbox.Any(model.Favorite_.Name.Contains(keyword, true), model.Favorite_.Description.Contains(keyword, true))).Find() } |
先に、いくつかデータを追加しておきます。
1 | curl -X POST http://localhost:1323/add -H 'Content-Type: application/json' -d '{ "name": "犬" , "Description": "かわいいから"}' |
1 | curl -X POST http://localhost:1323/add -H 'Content-Type: application/json' -d '{ "name": "酒" , "Description": "美味しいから"}' |
1 | curl -X POST http://localhost:1323/add -H 'Content-Type: application/json' -d '{ "name": "肉" , "Description": "美味しいから"}' |
確認
それでは、検索してみましょう!
まずは、「Name」で検索してみます。
1 2 | $ curl -X POST http://localhost:1323/find -d 'name=猫' [{"Id":1,"Name":"猫","Description":"モフモフだから","CreatedAt":"2019/10/03 12:52:12"}] |
次に、「Description」で検索してみます。
1 2 | $ curl -X POST http://localhost:1323/find -d 'description=かわいい' [{"Id":2,"Name":"犬","Description":"かわいいから","CreatedAt":"2019/10/03 12:56:52"}] |
最後にキーワードで検索してみます。
1 2 | $ curl -X POST http://localhost:1323/find -d 'keyword=から' [{"Id":1,"Name":"猫","Description":"モフモフだから","CreatedAt":"2019/10/03 12:52:12"},{"Id":2,"Name":"犬","Description":"かわいいから","CreatedAt":"2019/10/03 12:56:52"},{"Id":3,"Name":"酒","Description":"美味しいから","CreatedAt":"2019/10/03 12:57:06"}] |
うまく検索出来ていますね!
これで、検索の実装は完了です。
データを更新してみよう
「Name」をキーに、Descriptionの更新を実装してみます。
練習なので、検索してから更新して、更新結果をまた検索するように実装します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | package main import ( "go_example/model" "net/http" "time" "github.com/labstack/echo" "github.com/objectbox/objectbox-go/objectbox" ) func main() { e := echo.New() e.POST("/add", addFavorite) e.POST("/find", find) e.POST("/update", update) e.Logger.Fatal(e.Start(":1323")) } func update(c echo.Context) error { name := c.FormValue("name") description := c.FormValue("description") // パラメーターなしの場合はエラーで返す if name == "" && description == "" { return c.JSON(http.StatusNotFound, "param is not found") } box := getBox() // 検索 list, error := box.Query(model.Favorite_.Name.Equals(name, true)).Find() if error != nil { return c.JSON(http.StatusNotFound, "item not found") } // 更新 for _, item := range list { item.Description = description box.Put(item) } // 更新結果取得 list, error = box.Query(model.Favorite_.Name.Equals(name, true)).Find() if error != nil { return error } return c.JSON(http.StatusOK, list) } |
猫のDescriptionを「にゃーん」に変更してみます。
1 2 | $ curl -X POST http://localhost:1323/update -d 'name=猫&description=にゃーん' [{"Id":1,"Name":"猫","Description":"にゃーん","CreatedAt":"2019/10/03 12:52:12"}] |
データが更新されているのが確認できました!
データを全件取得してみよう
全件のデータを取得するのは、今までの実装の中で一番簡単です。
全件検索のメソッドを呼び出して結果を返すだけです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | package main import ( "go_example/model" "net/http" "time" "github.com/labstack/echo" "github.com/objectbox/objectbox-go/objectbox" ) func main() { e := echo.New() e.POST("/add", addFavorite) e.POST("/find", find) e.POST("/update", update) e.POST("/get/all", getAll) e.Logger.Fatal(e.Start(":1323")) } func getAll(c echo.Context) error { // テーブル呼び出し box := getBox() var list []*model.Favorite list, err := box.GetAll() if err != nil { return err } return c.JSON(http.StatusOK, list) } |
確認
それではリクエストしてみましょう。
1 2 | $ curl -X POST http://localhost:1323/get/all [{"Id":1,"Name":"猫","Description":"にゃーん","CreatedAt":"2019/10/03 12:52:12"},{"Id":2,"Name":"犬","Description":"かわいいから","CreatedAt":"2019/10/03 12:56:52"},{"Id":3,"Name":"酒","Description":"美味しいから","CreatedAt":"2019/10/03 12:57:06"}] |
全件取れましたね!
データを削除してみよう
次は、「Name」をキーに削除する処理を実装します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | package main import ( "go_example/model" "net/http" "time" "github.com/labstack/echo" "github.com/objectbox/objectbox-go/objectbox" ) func main() { e := echo.New() e.POST("/add", addFavorite) e.POST("/find", find) e.POST("/update", update) e.POST("/get/all", getAll) e.POST("remove", remove) e.Logger.Fatal(e.Start(":1323")) } func remove(c echo.Context) error { name := c.FormValue("name") if name == "" { return c.JSON(http.StatusNotFound, "param is not found") } box := getBox() // 検索 list, error := findName(box, name) if error != nil { return c.JSON(http.StatusNotFound, "item not found") } // 削除 for _, item := range list { box.Remove(item) } // 削除結果取得 list, error = findName(box, name) if error != nil { return error } |
確認
それでは、リクエストしてみましょう!
今入っているデータは、下記のとおりです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | [ { "Id": 1, "Name": "猫", "Description": "にゃーん", "CreatedAt": "2019/10/03 12:52:12" }, { "Id": 4, "Name": "肉", "Description": "美味しいから", "CreatedAt": "2019/10/03 16:32:38" }, { "Id": 6, "Name": "犬", "Description": "かわいいから", "CreatedAt": "2019/10/03 16:32:52" } ] |
「肉」を指定して、削除してみましょう。
1 2 | $ curl -X POST http://localhost:1323/remove -d 'name=肉' [{"Id":1,"Name":"猫","Description":"にゃーん","CreatedAt":"2019/10/03 12:52:12"},{"Id":6,"Name":"犬","Description":"かわいいから","CreatedAt":"2019/10/03 16:32:52"}] |
「肉」の項目が消えて、「猫」と「犬」のみになりましたね。
削除処理はこれで完了です!
第11回へつづく!
これで、ObjectBoxを用いたAPIの実装は終わりとなります。
簡単なアプリケーションやAPIなら有用じゃないでしょうか。
あまり認知度は高くないですが、多くの言語に対応しており、速度もそこそこ速いので ObjectBox はオススメです。
ぜひ使ってみてください!
なお、今回作成したgoファイルは、こちらのリポジトリにて管理しています。
次回の記事はこちら
オススメのGo入門本
こちらの記事もオススメ!
第1回の記事はこちら
書いた人はこんな人

- 新潟生まれ新潟育ち本業はモバイルアプリエンジニア。
日々、猫(犬)エンジニアとして活躍中!
IT技術9月 20, 2023開発効率を少しだけ上げるGithubActionsの便利な使い方
IT技術4月 7, 2023【ISUCON部】ライトコードISUCON部 始動!
IT技術4月 18, 2022【Android】Webでよくみる入力Boxを手作り
IT技術1月 19, 2022【Android】SeekbarでスイッチなUIを作る