LoginSignup
6
7

More than 5 years have passed since last update.

[golang] 「Gin」と「sqlx」を利用して簡単なAPIをつくってみた

Last updated at Posted at 2019-01-21

What's 「Gin」?

  • golangのフレームワークのひとつ
  • martiniという別のgolang frameworkのような感じですが、martiniよりも早いそう
  • contributors/star/fork/watchがechoやirisよりも多い (2019.01中旬時点)
  • HTTP2.0にも対応している
  • router がgroup化できる

[参照]
https://github.com/gin-gonic/gin

What's 「sqlx」?

  • golangの「database/sql」ライブラリを拡張したライブラリ
  • NamedQueryとかが簡単にできるようになってるので便利

[参照]
https://github.com/jmoiron/sqlx/

What did you do?

  • 「Gin」フレームワークで簡単なAPIを作ってみました
  • テーマは「本の管理システム」です
  • 基本的なCURDができるようにはなっています

Structure

├── Dockerfile                // API実行用 Docker image
├── api
│   ├── main.go               // API Server
│   └── scope
│       ├── book.go           // URI「/book」以下の処理
│       └── router.go         // HTTP Request Method毎に呼び出すメソッドを振り分ける
├── docker-compose.yml
└── mysql
    ├── Dockerfile            // mysql image
    ├── db-data
    ├── initdb.d
    │   ├── 1_init.sh
    │   ├── 1_schema.sql_     // mysql schema
    │   └── 2_testdata.sql_   // 初期データ
    └── my.cnf

Contents

※ コードや実行方法は github に上げましたので、興味ある方はそちらを御覧ください
以下、URIになります。

  • 検索
    • [GET] /book/list
    • [GET] /book/search/:title
  • 追加
    • [POST] /book/insert
  • 更新
    • [PATCH] /book/:id
  • 削除
    • [DELETE] /book/:id

Document

以下、ハマった箇所だけ簡単に解決法を紹介します。
(初心者なのでコードのあれこれ担保できないのであしからず)

■ argsを利用してselectする

[問題]

↓のようにargsを指定しなければstructsに結果を引き渡せるのですが、公式のように「$1」を指定するとまくいかなかった

 func getBookList(c *gin.Context) {
          db := dbConnect("mysql", "api", "api", "password")

          books := []Book{}
          db.Select(&books, "select * from book")

          c.String(200, "getBookList : %v", books)

[解決法]

  • 「?」を指定する

    err := db.Get(&book, "select * from book where id=?", id);
    
    • メモ:like検索のように「%」などの特殊文字を指定する時上手く行かなかった
  • Namedを利用する

    m := map[string]interface{}{"title": "%" + title + "%"}
    
    nstmt, err := db.PrepareNamed("select * from book where title like :title")
    ;
    err = nstmt.Select(&books, m)
    
    • メモ:「%」は事前に文字連結しておかないとエラーになってしまい、ハマった

■ HTTP Request Bodyを利用してパラメータを受け渡しする場合

[問題]

  • request bodyをどんなメソッドで引き取ればいいかがわからなかった

[誤答]

  • gin.Context.Resuest.Bodyを直接読み込もうとすること

    • これでやると、折角のフレームワークの旨味がまったく活かせない
    • しかもそのまま表示すると↓のようになる
    $ curl -X PATCH -d "title=RESTful web service&label=architecture" http://localhost:9000/book/st.sol.18
    updateBookInfo st.sol.18 : &{0xc000216140 <nil> <nil> false true {0 0} false false false 0x6a2030} 
    

[解決法]

  • Bind() を使う

    // update target info format is JSON
    var target Book
    if err := c.ShouldBind(&target); err != nil {
        c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})
        return
    }
    
6
7
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
7