• トップ
  • ブログ一覧
  • 【第10回】Go言語(Golang)入門~ObjectBox活用編~
  • 【第10回】Go言語(Golang)入門~ObjectBox活用編~

    笹川(エンジニア)笹川(エンジニア)
    2019.11.13

    IT技術

    第10回~Go言語(Golang)入門~

    秋山笹川先生

    (株)ライトコードの笹川(ささがわ)です!

    今回は、前回に引き続き、ObjectBox を利用して、 「echo + ObjectBox」のREST APIを作ってみようと思います!

    それでは、いってみましょう!

    前回の記事はこちら

    featureImg2019.11.06【第9回】Go言語(Golang)入門~ObjectBox導入編~第9回~Go言語(Golang)入門~笹川先生(株)ライトコードの笹川(ささがわ)です!前回は、Goの環境やパッケージ...

    データ追加エンドポイントを実装してみよう

    まずは、データの操作の前にテーブルの実装をします。

    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ファイルは、こちらのリポジトリにて管理しています。

    次回の記事はこちら

    featureImg2019.11.20【第11回】Go言語(Golang)入門~FCM送信編~第11回~Go言語(Golang)入門~笹川先生(株)ライトコードの笹川(ささがわ)です!今回は、Firebase C...

    オススメのGo入門本

    Goプログラミング実践入門 標準ライブラリでゼロからWebアプリを作る
    Goプログラミング実践入門 標準ライブラリでゼロからWebアプリを作る

     

    こちらの記事もオススメ!

    featureImg2020.08.08Go言語 特集知識編人気急上昇中のGo言語(Golang)って何だ?実装編Go言語(Golang)入門...

    featureImg2020.07.17ライトコード的「やってみた!」シリーズ「やってみた!」を集めました!(株)ライトコードが今まで作ってきた「やってみた!」記事を集めてみました!※作成日が新し...

    第1回の記事はこちら

    featureImg2019.09.13【第1回】Go言語(Golang)入門~環境構築編~第1回~Go言語(Golang)を習得したい!~笹川先生(株)ライトコードでモバイルアプリケーション開発をしている笹川...

    ライトコードでは、エンジニアを積極採用中!

    ライトコードでは、エンジニアを積極採用しています!社長と一杯しながらお話しする機会もご用意しております。そのほかカジュアル面談等もございますので、くわしくは採用情報をご確認ください。

    採用情報へ

    笹川(エンジニア)

    笹川(エンジニア)

    おすすめ記事

    エンジニア大募集中!

    ライトコードでは、エンジニアを積極採用中です。

    特に、WEBエンジニアとモバイルエンジニアは是非ご応募お待ちしております!

    また、フリーランスエンジニア様も大募集中です。

    background