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