概要
前回の続き。
前回 プログラミング初学者向け Go入門 #1
前回はGoプロジェクトを作成して起動までやったので、今回はDBを使用していく。
これも超簡単。
今回のソース
準備
前回同様、git cloneしたあと、mysqlを入れていない人はmysqlの設定から。
参考 : https://qiita.com/hkusu/items/cda3e8461e7a46ecf25d
mysqlの準備ができたら、dbの追加をする
mysql> create database gosample;
go-sql-driverをインストール
run $ go get -u github.com/go-sql-driver/mysql
ディレクトリ構成
.
├── README.md
├── app
│ ├── controller
│ │ └── app.go
│ ├── db
│ │ └── db.go
│ ├── models
│ │ └── user.go
│ └── view
│ ├── detail.html
│ ├── footer.html
│ ├── header.html
│ ├── home.html
│ └── index.html
├── public
│ ├── css
│ │ └── bootstrap-3.3.6.min.css
│ ├── fonts
│ │ ├── glyphicons-halflings-regular.ttf
│ │ ├── glyphicons-halflings-regular.woff
│ │ └── glyphicons-halflings-regular.woff2
│ ├── img
│ │ └── favicon.png
│ └── js
│ ├── bootstrap-3.3.6.min.js
│ └── jquery-2.2.4.min.js
└── run
├── main
├── main.go
├── run
└── src
└── github.com
└── go-sql-driver
└── mysql
├── AUTHORS
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── appengine.go
├── auth.go
├── auth_test.go
├── benchmark_test.go
├── buffer.go
├── collations.go
├── connection.go
├── connection_test.go
├── const.go
├── driver.go
├── driver_test.go
├── dsn.go
├── dsn_test.go
├── errors.go
├── errors_test.go
├── fields.go
├── infile.go
├── packets.go
├── packets_test.go
├── result.go
├── rows.go
├── statement.go
├── statement_test.go
├── transaction.go
├── utils.go
└── utils_test.go
起動方法
ターミナルでrunディレクトリに移動する。
run $ go run main.go
内容
重要な部分だけここで紹介。
- sample_golang_2/app/controller/app.go
// Home is method to render Name page.
func Home(rw http.ResponseWriter, request *http.Request){
tmpl := parseTemplate()
// db connection
dbm := db.ConnDB()
users := []models.User{}
rows, err := dbm.Query("select id, name from users")
for rows.Next() {
user := models.User{}
if err = rows.Scan(&user.ID, &user.Name); err != nil {
// 変換に失敗した場合、INDEX画面表示
toIndex(tmpl, rw, request, "ユーザ データ変換 失敗", err)
return
}
users = append(users, user)
}
// HOME画面表示
err = tmpl.ExecuteTemplate(rw, "home.html", struct {
Users []models.User
}{
Users: users,
})
if err != nil {
outputErrorLog("HTML 描画 エラー", err)
}
}
// Detail is method to render Detail page.
func Detail(rw http.ResponseWriter, request *http.Request){
tmpl := parseTemplate()
// ID取得
id := request.URL.Query().Get("id")
log.Println("id : ", id)
// db connection
dbm := db.ConnDB()
user := new(models.User)
row := dbm.QueryRow("select id, name from users where id = ?", id)
if err := row.Scan(&user.ID, &user.Name); err != nil {
// 変換に失敗した場合、INDEX画面表示
toIndex(tmpl, rw, request, "ユーザ データ変換 失敗", err)
return
}
// Detail画面表示
err := tmpl.ExecuteTemplate(rw, "detail.html", struct {
User *models.User
}{
User: user,
})
if err != nil {
outputErrorLog("HTML 描画 エラー", err)
}
}
// ユーザー情報更新
func Edit(rw http.ResponseWriter, request *http.Request){
tmpl := parseTemplate()
// 変更する名前とIDを取得
err := request.ParseForm()
if err != nil {
// パースに失敗したらエラー
toIndex(tmpl, rw, request, "フォーム パース エラー", err)
return
}
name := request.Form.Get("name")
log.Println("変更する名前:", name)
id := request.Form.Get("id")
log.Println("変更する対象ID:", id)
// db connection
dbm := db.ConnDB()
_, err = dbm.Exec("update users set name = ? where id = ?", name, id)
if err != nil {
log.Println("ユーザー 更新 失敗")
} else {
log.Println("ユーザー 更新 成功")
log.Println("更新したユーザーID:", id)
}
// HOME画面表示
http.Redirect(rw, request, "/home", http.StatusFound)
}
DBの
-
複数行検索
-
単一行検索
-
更新
をし、GET/POSTメソッドのvalueの受け取り、値の画面への受け渡しをしている。
ここを抑えてしまえば、単純なwebアプリケーションは大概作成できるといっても過言ではないはず。 -
sample_golang_2/app/db/db.go
import (
"database/sql"
"log"
_ "github.com/go-sql-driver/mysql"
)
var db *sql.DB
// InitDB is method to initialize DB
func InitDB() {
// DB接続
log.Println("== DB 接続 ==")
db, err := sql.Open("mysql", "root@/gosample")
if err != nil {
log.Println("DB 接続 エラー")
log.Fatalln(err)
}
log.Println("== DB 接続 成功 ==")
// 既存のテーブル削除
log.Println("== DB 削除 ==")
db.Exec("DROP TABLE users")
log.Println("== DB 削除 成功 ==")
// テーブル生成
log.Println("== DB テーブル 作成 ==")
_, err = db.Exec(`CREATE TABLE users (
id INTEGER AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(32) NOT NULL
)`)
if err != nil {
outputErrorLog("usersテーブル作成失敗", err)
}
// データ投入
log.Println("== DB データ投入 ==")
_, err = db.Exec(`INSERT INTO users
(name)
VALUES
('George Washington'),
('John Adams'),
('Thomas Jefferson'),
('James Madison')
`)
if err != nil {
outputErrorLog("データ投入 失敗", err)
}
log.Println("== DB データ投入 完了 ==")
}
// CloseDB is method to close DB connection
func CloseDB() {
if db != nil {
db.Close()
}
}
// ConnDB is method to get DB connection
func ConnDB() *sql.DB {
if db == nil {
var err error
db, err = sql.Open("mysql", "root@/gosample")
if err != nil {
log.Println("DB 接続 エラー")
log.Fatalln(err)
}
}
return db
}
// output error log and stop app
func outputErrorLog(message string, err error) {
log.Println(message)
log.Fatalln(err)
}
ここではDB接続と、初期データの投入をしている。
github.com/go-sql-driver/mysql
を使用すれば、sql.Open
でコネクションができるので簡単。
アプリケーションでは多用するので、コネクション接続はファンクション化しておくのが良いと思う。
実際に動かしてみる
TOP画面
### ユーザー 一覧画面 ### ユーザーデータ編集画面 ### 編集する ### 更新ボタンクリック後更新されました。
次回
ログイン画面を実装し、基本的なWEBアプリケーションのセキュリティ設定をしていく。
が、最後かな。
アイデアがあれば作るけど、なかなか思いつかない。