アプリケーションは、データを継続的に保持しなければなりません。データを保持するためには、データベース(database)というものを使います。データベースには色々なものがありますが、今回は、軽量でシンプルな SQLite を使いたいと思います。
データベースを実際に使うには、ORM(Object_relation mapping、オブジェクト関係マッピング)と呼ばれるものを使って、プログラミング言語とデータベースを関連づけます。GORM は、Go のための ORM です。
SQLite と GORM の環境設定は簡単です。ターミナルに次のように入力してエンターキーを押すだけです。macOS、Mint(Ubuntu)、CentOS 7で同じコードです。少し時間がかかる場合があります。
go get github.com/jinzhu/gorm
go get github.com/mattn/go-sqlite3
今回は、データベースを使って、Todo アプリケーションを作ります。
次のようなディレクトリ構成にします。
gin/
- main.go
- templates/
- - index.html
- styles/
- - style.css
ディレクトリ構成、ディレクトリ名、ファイル名は自由に決めて大丈夫です。
package main
import (
"github.com/gin-gonic/gin"
"github.com/jinzhu/gorm"
// gorm でデータベース操作を行うため、sqlite3 は読み込むが、_ で使わないことを明示する
_ "github.com/mattn/go-sqlite3"
)
// データ構造(モデル)の宣言
type Todo struct {
gorm.Model
Memo string
}
func main() {
r := gin.Default()
r.Static("styles", "./styles")
r.LoadHTMLGlob("templates/*")
dbInit()
r.GET("/", getHandler)
r.POST("/new", postHandler)
r.Run()
}
func getHandler(c *gin.Context) {
todo := getAll()
c.HTML(200, "index.html", gin.H{"todo":todo})
}
func postHandler(c *gin.Context) {
memo := c.PostForm("memo")
create(memo)
c.Redirect(302, "/")
}
// データベースのマイグレート(初期化)
func dbInit() {
db, err := gorm.Open("sqlite3", "todo.sqlite3")
if err != nil {
panic("failed to connect database\n")
}
db.AutoMigrate(&Todo{})
}
// データの作成
func create(memo string) {
db, err := gorm.Open("sqlite3", "todo.sqlite3")
if err != nil {
panic("failed to connect database\n")
}
db.Create(&Todo{Memo: memo})
}
// 全部のデータを取得
func getAll() []Todo {
db, err := gorm.Open("sqlite3", "todo.sqlite3")
if err != nil {
panic("failed to connect database\n")
}
var todo []Todo
db.Find(&todo)
return todo
}
初期化のところで、マイグレート(migrate)という用語が出てきました。普通の初期化は、データをすべて書き替えますが、マイグレートは、データベースに保存されているデータを保持したまま、データの追加・削除・変更を行います。データファイルがなければ新しいデータファイルを作成します。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Todo</title>
<link rel="stylesheet" href="../styles/style.css">
</head>
<body>
<h1>Todo</h1>
<div align="center">
<form method="post" action="/new">
<p>メモ<input type="text" name="memo" size="30" placeholder="入力してください">
<input type="submit" value="登録"></p>
</form>
</div>
<div class="container">
<ul>
{{ range .todo }}
<li>{{.Memo}}</li>
{{ end }}
</ul>
</div>
</body>
</html>
body {
color: gray;
}
h1 {
text-align: center;
font-family: sans-serif;
font-weight: 100;
border-bottom: 1px solid lightgray;
}
.container {
width: 330px;
margin: auto;
font-size: 14px
}
実行する場合は、ターミナルで gin ディレクトリに移動して、go run main.go と入力して、エンターキーを押します。
go run main.go
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
- using env: export GIN_MODE=release
- using code: gin.SetMode(gin.ReleaseMode)
[GIN-debug] GET /styles/*filepath --> github.com/gin-gonic/gin.(*RouterGroup).createStaticHandler.func1 (3 handlers)
[GIN-debug] HEAD /styles/*filepath --> github.com/gin-gonic/gin.(*RouterGroup).createStaticHandler.func1 (3 handlers)
[GIN-debug] Loaded HTML Templates (3):
-
- .DS_Store
- index.html
[GIN-debug] GET / --> main.getHandler (3 handlers)
[GIN-debug] POST /new --> main.postHandler (3 handlers)
[GIN-debug] Environment variable PORT is undefined. Using port :8080 by default
[GIN-debug] Listening and serving HTTP on :8080
Gin の場合は、多くのコードが表示されます。
macOS の場合は、次のようなアラートが表示される場合があります。「許可」をクリックしてください。
ブラウザで localhost:8080/ にアクセスすると次のように表示されます。Gin では、ポートは、自動的に、8080 なるみたいです。