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

#はじめに
こんにちは。某学校でプログラミング等の勉強中のサーバーサイドのプログラマーのワタタクです。:relaxed:
今回は久し振りにGoの記事になります。今回のテーマは「gorm」。
「gorm」って何？から使い方などについてまとめていきたいと思います。
では早速やっていきましょう。
#gormとは
GO言語用のORMフレームワーク。
DB周りの処理を実装する時にこのフレームワークを使うと便利。

- 公式サイト:
[http://doc.gorm.io/](http://doc.gorm.io/)

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

#実践（テーブル定義)
※今回はusersテーブルを作ります。

```golang:models/user.go
import "github.com/jinzhu/gorm"

type User struct {
	gorm.Model
	Name string 
	Sex  uint64 
	Age  uint64 
}
```
ここで出てきた``gorm.Model``とはgormが用意してくれているモデル。
以下中身

```golang: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"`
}
```

#コントローラ

```golang: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)
}
```
**マイグレーションを実行するとテーブルが無い時は自動生成あるときはなにもしない**

```golang
db = db.Set("gorm:table_options", "ENGINE=InnoDB CHARSET=utf8 auto_increment=1")
db.DB()
db.AutoMigrate(&models.User{})
DB = db
```
#実践(データ操作)
##更新系
###INSERT

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

```golang: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

```golang:controllers/DataAccess.go
id := 対象ID

user := []models.User{}
DB.Delete(&user, id)
```
##参照系
###複数

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

DB.Find(&users)

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

```golang: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句と同じです。なので、複数の条件で指定する時は以下のようになります。*

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