LoginSignup
2
3

More than 5 years have passed since last update.

Go言語を真剣に勉強してみた〜gormを使ってのORM〜

Posted at

はじめに

こんにちは。某学校でプログラミング等の勉強中のサーバーサイドのプログラマーのワタタクです。:relaxed:
今回は久し振りにGoの記事になります。今回のテーマは「gorm」。
「gorm」って何?から使い方などについてまとめていきたいと思います。
では早速やっていきましょう。

gormとは

GO言語用のORMフレームワーク。
DB周りの処理を実装する時にこのフレームワークを使うと便利。

そもそもORMって何?

Object-Relational-Mappingの略で、日本語ではオブジェクト関係マッピングと呼ばれるものです。具体的には、オブジェクト指向プログラムとリレーショナルデータベースをつなぐ役割をしてくれます。
ORMを使用することでより直感的にRDBの操作をすることができると思います。

実践(テーブル定義)

※今回はusersテーブルを作ります。

models/user.go
import "github.com/jinzhu/gorm"

type User struct {
    gorm.Model
    Name string 
    Sex  uint64 
    Age  uint64 
}

ここで出てきたgorm.Modelとはgormが用意してくれているモデル。
以下中身

model.go
package gorm

import "time"

// Model base model definition, including fields `ID`, `CreatedAt`, `UpdatedAt`, `DeletedAt`, which could be embedded in your models
//    type User struct {
//      gorm.Model
//    }
type Model struct {
    ID        uint `gorm:"primary_key"`
    CreatedAt time.Time
    UpdatedAt time.Time
    DeletedAt *time.Time `sql:"index"`
}

コントローラ

controllers/gorm.go
import (
  "github.com/jinzhu/gorm"
  _ "github.com/jinzhu/gorm/dialects/mysql"
)

var DB *gorm.DB

func InitDB() {
    db, err := gorm.Open("mysql", getConnectionString())

    if err != nil {
        panic(err)
    }

    db = db.Set("gorm:table_options", "ENGINE=InnoDB CHARSET=utf8 auto_increment=1")
    db.DB()
    db.AutoMigrate(&models.User{})
    DB = db
}

func getConnectionString() string {
    host := getParamString("db.host", "localhost(ホスト名)")
    port := getParamString("db.port", "3306(ポート番号)")
    user := getParamString("db.user", "データベース名")
    pass := getParamString("db.password", "パスワード")
    dbname := getParamString("db.name", "ユーザー名")
    protocol := getParamString("db.protocol", "tcp")
    dbargs := getParamString("dbargs", " ")
    timezone := getParamString("db.timezone", "parseTime=true&loc=Asia%2FTokyo")

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

マイグレーションを実行するとテーブルが無い時は自動生成あるときはなにもしない

db = db.Set("gorm:table_options", "ENGINE=InnoDB CHARSET=utf8 auto_increment=1")
db.DB()
db.AutoMigrate(&models.User{})
DB = db

実践(データ操作)

更新系

INSERT

controllers/DataAccess.go
user := &models.User{
    Name: "ワタタク",
    Sex:  "男",
    Age:  22,
}
DB.Create(&user)

UPDATE

controllers/DataAccess.go
idint := 対象ID

user := &models.User{
   Name: "###",
   Sex: 000,
   Age: 000,
}

DB.First(&user, idint)

user.Name = "###"
user.Sex = 000
user.Age = 000

DB.Save(&user)

DELETE

controllers/DataAccess.go
id := 対象ID

user := []models.User{}
DB.Delete(&user, id)

参照系

複数

controllers/DataAccess.go
users := []models.User{}

DB.Find(&users)

/*
 *where句
 */
DB.Find(&user, "age=?", "", 22)
//このようにすることで、年齢が22才のレコードを抽出してくれる。配列の1つ1つにuserの1レコードが格納されているはずです。

単数

controllers/DataAccess.go
users := []models.User{}

models.Id = 12
db.First(&users) 
/*
 *もしくはwhere句っぽく
 */
db.First(&user, "name=?", "test")

基本的に構造体の情報を元にテーブルを参照して、引数に渡した構造体の情報を埋めたり、削除したりします。
この例では、usersテーブルのidが12のレコードを引っ張ってきています。idは主キー(上図)なので、指定すれば確実にidが12のレコードを1つ取ってこれます。userを出力してみるとidが12のレコードの情報で埋まっているはずです。つまり、userが1レコードを表しています。最初に指定するのはIDに限らず、レコードを1つ特定できる情報を与えれば大丈夫です。

DB.Firstの場合との違いは、引数の変数が配列である点と条件の指定の仕方です。引っ張ってきた複数のレコードを格納するために構造体を配列でインスタンス化します。そして、先ほどは直接レコード情報の何かを指定していましたが、今回はDB.Findの引数で条件を指定します。要はwhere句と同じです。なので、複数の条件で指定する時は以下のようになります。

以上。
もし何か間違っている等のご指摘があればご連絡ください。
最後まで読んで頂きありがとうございました。

2
3
0

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
2
3