前回の内容に引き続き、revelとMySQLを頑張ってみます。

開発環境 (前記事と同じ)

あとでdocker化するのでしっかり書かないけど、とりあえずmac上で
Goがすでに入っているのが前提

とりあえずのゴール

  • rootページで「it works!」が出る (前回の内容を参照)
  • mysqlと接続して、テーブルからデータを取得できるようにする(/users/を取ってくる、/users/1を取ってくる、くらい)(今回はここまで)

Revel framework あと、revelでMySQLを使うとなると、GORMがよく使われているようなので、これも今回使います


0.まずはファイル構成について
myapp
  -- app
   -- controller[いわゆるコントローラ]
   -- routes[まだ触ってない]
   -- tmp[まだ触ってない]
   -- views[いわゆるビュー。APIのためのアプリケーションなので多分今後触ることもない)
   -- init.go[アプリケーションの起動時に走る処理っぽい]
  -- conf
   --- app.conf[コンフィグレーション]
   --- routes[ルートを書く。Raisだと見慣れているであろうアレ]

今回の作業では、

  • controller
  • init.go
  • app.conf
  • routes
    を触ることになります

1.必要なパッケージの取得 MySQLとGORM

go get github.com/jinzhu/gorm
go get github.com/go-sql-driver/mysql

2.DB接続情報をapp.confに記入
myapp/conf/app.conf それぞれ必要情報を以下の感じで入力

db.user = USR_NAME
db.password = PASSWORD
db.host = IP_ADDRESS
db.port = PORT_NUM
db.name = DB_NAME
db.protocol = TCP

3.DBに接続する
DB接続設定用のファイル myapp/controllers/gorm.goを作成(controllerにすべきかmodelにすべきかよくわかってない)

type GormController struct {
    *revel.Controller
    Txn *gorm.DB
}
var Gdb *gorm.DB
// init db
func InitDB() {
    //TODO あとで変更する
    _ := GetDBConn()
}
func GetDBConn() *gorm.DB {
    var err error

connectionString := getConnectionString()

    Gdb, err = gorm.Open("mysql", connectionString)

    if err != nil {
        revel.ERROR.Println("FATAL", err)
        panic( err )
    }
    Gdb.DB()
    Gdb.LogMode(true)

    return Gdb
}

func getParamString(param string, defaultValue string) string {
    p, found := revel.Config.String(param)
    if !found {
        if defaultValue == "" {
            revel.ERROR.Fatal("Cound not find parameter: " + param)
        } else {
            return defaultValue
        }
    }
    return p
}

func getConnectionString() string {
    host := getParamString("db.host", "")
    port := getParamString("db.port", "3306")
    user := getParamString("db.user", "")
    pass := getParamString("db.password", "")
    dbname := getParamString("db.name", "auction")
    protocol := getParamString("db.protocol", "tcp")
    dbargs := getParamString("dbargs", " ")

    if strings.Trim(dbargs, " ") != "" {
        dbargs = "?" + dbargs
    } else {
        dbargs = ""
    }
    return fmt.Sprintf("%s:%[email protected]%s([%s]:%s)/%s%s",user, pass, protocol, host, port, dbname, dbargs)
}

// このSetDBで、GormControllerにDB情報を持たせる。  
//今後作っていくcontrollerはGormControllerを引き継ぐことで、DBへのアクセスを可能にする
func (c *GormController) SetDB() revel.Result {
    c.Txn = Gdb
    return nil
}

4.DBに接続する上記処理を、アプリケーション軌道の最初で走らせる myapp/controllers/init.goを作成

package controllers

import "github.com/revel/revel"

func init() {
    revel.OnAppStart(InitDB) // GormControllerのInitを呼び出してDB接続する
    revel.InterceptMethod((*GormController).SetDB, revel.BEFORE) //DB情報インスタンスを設定

}

5.userの作成
今回はとりあえず、user情報を持ってみる。myapp/models/user.goを作成

package models

type User struct {
    Id              int64     `gorm:"primary_key" json:"id"`
    Name            string        `json:"name"`
}

6.userコントローラの作成
myapp/controllers/users.goを作成
今回はリスト取得のIndexと、1つだけ取得するShowのみ

package controllers

import (
    "github.com/revel/revel"
    "myapp/app/models"
    "net/http"
)

type UsersController struct {
    GormController //GormControllerを継承することで、以下でc.TxnでDBへアクセス可能
}

func (c UsersController) Index() revel.Result {

    users := []models.User{}

    c.Txn.Find(&users)

    return c.RenderJSON(users)
}
func (c UsersController) Show(userID int64) revel.Result {

    user := models.User{}

    c.Txn.First(&user, userID)

    return c.RenderJSON(user)
}

7.ルートの登録
Index,Showにルーティングされるようにします
myapp/conf/routesを編集

GET     /                                       AppController.Index //これがデフォルトのパス
GET     /users                                  UsersController.Index
GET     /users/:userID                          UsersController.Show

8.アプリケーションからDBマイグレーション
アプリケーションを起動したら、モデルの記載に応じてDBがマイグレートされるようにしておきます myapp/controllers/gorm.goを編集

func InitDB() {
  //接続したDBを取得して、マイグレーションの対象モデルを追加
    db := GetDBConn()
    db.AutoMigrate(models.User{})
}

9.DBへのデータ追加
めんどくさいのでここでは手動でデータを入れています。
最低限のモデルにしてあるので、適当にユーザーの名前だけ入れればOK

10.動かしてみる
※こちらの環境では、APIのレスポンスをいじったりとか色々しているので、実際に上記と同様の環境では試していないですが...
追加したユーザーのリスト、ユーザー個別情報の取得を以下のリクエストで取ってみる

localhost:9000/users
localhost:9000/users/1


やってみての感想

  • gormあたりとか、どういう構成がいいのかよくわからなかったのでだいぶ迷走した
  • controllers/init.goがあればこれが最初に実行されるというのは知らず、またその中でのrevel.InterceptMethod((*GormController).SetDB, revel.BEFORE)みたいな魔法もよくわからなかった(わかってない)ので、各コントローラーからどうやってDB接続するのが良いのかは探し回った

参考記事

Revel + GORM を使う(アプリケーション作成Model作成編)
RevelでGORMを使ったMySQL Associationの実装
GORMというORMが超絶便利だった件
【GORM】Go言語でORM触ってみた golangのフレームワークrevelを使用して掲示板っぽいものを作ってみる
Go言語 + webFramework revelで、MYSQLを使用する

関連記事

この記事へのコメント

まだコメントはありません
1
@cueighoryの技術ブログ
1
このエントリーをはてなブックマークに追加