LoginSignup
1
3

More than 5 years have passed since last update.

プログラミング初学者向け Go入門 #2

Last updated at Posted at 2018-11-29

概要

前回の続き。
前回 プログラミング初学者向け 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画面

スクリーンショット 2018-11-29 16.42.04.png

ユーザー 一覧画面

スクリーンショット 2018-11-29 16.42.09.png

ユーザーデータ編集画面

スクリーンショット 2018-11-29 16.42.40.png

編集する

スクリーンショット 2018-11-29 16.42.53.png

更新ボタンクリック後

スクリーンショット 2018-11-29 16.42.56.png

更新されました。

次回

ログイン画面を実装し、基本的なWEBアプリケーションのセキュリティ設定をしていく。
が、最後かな。
アイデアがあれば作るけど、なかなか思いつかない。

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