Go/Gin  Gormでよく使うDB操作 + 簡単なアプリ作成

# Gin勉強の備忘録
Gormの簡単なまとめ + Gormを使用した簡単なWebアプリ作成
## Gormとは
Go言語専用のORMライブラリ。
構造体を引数に渡すことによって簡単にDB操作が可能。
## Gormを使うには
下記のインストールを行う（ファイルgo.modがないとインストール不可）
```terminal
go get -u gorm.io/gorm
go get -u gorm.io/driver/sqlite
```

mainやinit内でDBファイル作成&開く
```go
db, err := gorm.Open(sqlite.Open(DBName), &gorm.Config{})
if err != nil{
    log.Fatalln(err)
}
```

## よく使うCRUD
### レコードの作成
```go
db.Create(&構造体)
```
### レコードの更新（単一のカラム）
```go
db.Model(&構造体{}).Where("カラム名 = ?", 検索値).Update(カラム名, 更新値)
```

### レコードの更新（複数のカラム）
例）以下条件時
```go
type User struct{
    name string
    age int
}

user := User{name: "foo", age: "20"}
```
```go
db.Model(&User{}).Updates(user)
```

### レコードの取得（単一のオブジェクト）
構造体にオブジェクトが入る
```go
db.Where("カラム名 = ?", 検索値).First(&構造体)
```

### レコードの取得(すべて)
例）以下条件時
```go
type User struct{
    name string
    age int
}

var users []User
```

```go
db.Find(&users)
```

### レコードの削除

同じ意味

```go
db.Where("カラム名 = ?", 検索値).Delete(&構造体{})

db.Delete(&構造体{}, "カラム名 = ?", 検索値)
```

### 補足
gorm.Modelを使用すると、下記要素が自動で追加される
IDやCreatedAtなど値を入れなくても自動で入力されるため便利
![Screen Shot 2022-12-18 at 2.06.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3039114/02d4f903-bd5e-4890-ac08-8fd476451d56.png)
使い方
```go
type User struct{
    gorm.Model
    name string
    〜〜〜〜
    〜〜〜〜
}

```

## Gormを使用した簡単なWebアプリ
名簿リストアプリ
作成時間30分
【環境】
OS:Mac
コードエディタ:Visual Studio Code
### コード
```
sample
    ├── main.go
    ├── models
    │     └── db.go
    └── views
          └── index.html
```

```go:main.go
package main

import (
	"net/http"
	db "sample/models"
	"strconv"

	"github.com/gin-gonic/gin"
)

func main() {
	router := gin.Default()
	router.LoadHTMLGlob("views/*.html")

	router.GET("/", func(ctx *gin.Context) {
		users := db.SelectAllUser()
		ctx.HTML(http.StatusOK, "index.html", gin.H{
			"users": users,
		})
	})

	router.POST("/", func(ctx *gin.Context) {
		name := ctx.PostForm("name")
		age, _ := strconv.Atoi(ctx.PostForm("age"))
		db.AddUser(name, age)
		ctx.Redirect(http.StatusFound, "/")
	})

	router.Run()
}
```
```go:db.go
package db

import (
	"log"

	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
)

const DBName = "sample.db"

type User struct {
	gorm.Model
	Name string
	Age  int
}

// エラーチェック
func CheckError(err error) {
	if err != nil {
		log.Fatalln(err)
	}
}

func init() {
	db := openDB()
	db.AutoMigrate(&User{})
}

// ユーザー追加
func AddUser(name string, age int) {
	db := openDB()
	user := User{Name: name, Age: age}
	db.Create(&user)
}

//ユーザー全取得
func SelectAllUser() []User {
	var users []User
	db := openDB()
	db.Find(&users)
	return users
}

// データベース開く
func openDB() (db *gorm.DB) {
	db, err := gorm.Open(sqlite.Open(DBName), &gorm.Config{})
	CheckError(err)
	return db
}
```
```html:index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <title>index</title>
</head>
<body>
    <form action="/" method="post">
        名前:<input type="text" name="name"/>
        年齢:<input type="number" name="age"/>
        <input type="submit" value="確定"/>
    </form>
    <br/><br/>

    <ul>
        {{range .users}}
            <li><h3>{{.Name}} {{.Age}}歳</h3></li>
        {{end}}
    </ul>
</body>
</html>
```

### 実行結果
名前と年齢を入力後、確定クリック
![Screen Shot 2022-12-18 at 2.00.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3039114/c1892e17-bee2-1ab0-45bf-4f8b3d35879d.png)


データベースに追加され、一覧に表示される
![Screen Shot 2022-12-18 at 2.01.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3039114/d36eef3c-52ff-085d-e6e2-7c194837c7f1.png)


### データベース内の確認

プロジェクト直下で下記入力でsample.dbファイル開く
```terminal:Terminal
sqlite3 sample.db
```
sample.db内のテーブルの確認
```terminal:Terminal
.table
```
usersテーブル内の確認
```sql:Terminal
select * from users;
```
しっかり追加されてる
```terminal
1|2022-12-18 01:59:52.362826+09:00|2022-12-18 01:59:52.362826+09:00||田中　太郎|20
2|2022-12-18 02:01:16.899277+09:00|2022-12-18 02:01:16.899277+09:00||山田　花子|19
```
sample.dbファイル閉じる
```terminal:Terminal
.exit
```