はじめに
GoでなにかしらのWebアプリケーションを作成したいと思いました。
今回は単語アプリを作りました。
githubのページです。
word_and_meaning_keep
このサイトの使い方
1.このサイトは単語とその意味を記録できるサイトです
アカウントを持っている場合はそのままログイン
お持ちでない場合には「新規ユーザーの登録」より
登録をお願いします
2.単語が登録されている場合はログインすると表示されます
登録されていない場合は登録をしてお使いください
こだわりポイント
ログインユーザーごとにwordを表示させたこと
デモ動画
作るもの
単語とその意味をMySQLに記録していくものです。さらにはログイン機能も実装してユーザーごとに単語一覧を表示していくものとなります。
勉強したもの
今回、私はGoをA Tour of Goで基礎知識を習得しました。
次にWebアプリケーションを作成するにあたってGoプログラミング実践入門: 標準ライブラリでゼロからWebアプリを作るを読みました。
MySQLについては一週間で身につくMySQLで簡単に勉強しました。
Webサーバー
今回はWebサーバーをGoで立てました。net/httpパッケージをつかいました。
package main
import(
"net/http"
)
func main(){
http.ListenAndServe(":8080", nil)
}
とても簡単に立てることができます。これはなにもレスポンスを返しません。レスポンスを返すにはハンドラを扱います
ハンドラ
これを使ってURLごとに処理をします。
func HandlerUserForm(w http.ResponseWriter, r *http.Request) {
処理内容
}
func main(){
http.HandleFunc("/user-form", HandlerUserForm){
処理の中身
}
テンプレート
Goのテンプレート機能を使用。'html/template'を使用します。これを使うとhtmlにアクションとして表示することができます。
// テンプレートをパースする
func HandlerUserConfirm(w http.ResponseWriter, req *http.Request) {
tpl := template.Must(template.ParseFiles("templates/user-confirm.html"))
// テンプレートに出力する値をマップにセット
values := map[string]string{
"account": req.FormValue("account"),
"passwd": req.FormValue("passwd"),
}
fmt.Println("登録", values["account"]) //登録した名前が出る
//dbに登録
db.User_db(values["account"], values["passwd"])
// マップを展開してテンプレートを出力する
if err := tpl.ExecuteTemplate(w, "user-confirm.html", values); err != nil {
fmt.Println(err)
}
}
htmlの文章中に以下のようにします
<p>{{ . }}</p>
これでhtml上でGoからの結果を受け取り表示することができます。
MySQLを扱う
GoでMySQLを扱うには'Go-MySQL-Driver'を使わなければいけません。そこでインストールするためにgo.modを作らなければいけないのです。
go mod init wordapp
これでgo.modが作られます'wordapp'の部分は任意の文字で大丈夫です。
これを作った後は次のコマンドでMySQLのドライバーを入手します。
go get -u github.com/go-sql-driver/mysql
これで一通りの準備は完了です。
今度はgoを書いていきます。
package db
import (
"database/sql"
"fmt"
"log"
_ "github.com/go-sql-driver/mysql"
)
// ユーザー登録の関数
func User_db(name string, password string) {
//sql.Open("mysql", "user:password@/dbname")
db, err := sql.Open("mysql", "root:yourpassword@tcp(localhost:3306)/english_word_app")
if err != nil {
panic(err.Error())
}
defer db.Close()
rows, err := db.Query("SELECT id FROM user WHERE id = (SELECT MAX(id) FROM user);")
if err != nil {
log.Fatal(err)
}
var id *int
for rows.Next() {
if err := rows.Scan(&id); err != nil {
fmt.Println("idスキャンに失敗")
log.Fatal(err)
}
}
// プリペアードステートメントを使用
in, err := db.Prepare("INSERT INTO user(id ,name,password) VALUES(?,?,?)")
if err != nil {
fmt.Println("データベース接続失敗")
panic(err.Error())
} else {
fmt.Println("データベース接続成功")
}
defer db.Close() //最後に閉じる
//insert
result, err := in.Exec(*id+1, name, password)
if err != nil {
panic(err.Error())
}
lastId, err := result.LastInsertId()
if err != nil {
panic(err.Error())
}
fmt.Println(lastId)
}
これを使うとDBに接続してINSERETができます。
'english_word_app'はDB名です
このファイルはdbというディレクトリの下にあるので
package db
となります。
package db
import (
"database/sql"
"fmt"
"log"
_ "github.com/go-sql-driver/mysql"
)
// ログインのための関数
func User_login(name string, password string) int {
//sql.Open("mysql", "user:password@/dbname")
db, err := sql.Open("mysql", "root:yourpassword@tcp(localhost:3306)/english_word_app")
if err != nil {
panic(err.Error())
}
defer db.Close()
rows, err := db.Query("SELECT id,name,password FROM user WHERE name=\"" + name + "\"and password=\"" + password + "\";")
if err != nil {
fmt.Println("select失敗")
log.Fatal(err)
}
var (
id *int
)
for rows.Next() {
if err := rows.Scan(&id, &name, &password); err != nil {
fmt.Println("スキャンに失敗")
log.Fatal(err)
}
}
m := 0
if id == nil {
//何もない場合は入力が間違いとして戻り値を0で返す
id = &m
return *id
} else {
return *id
}
}
ここではSELECTをしています。userからid,name,passwordを取得します
userとwordのDB管理
今回はuserの新規登録の際にidを登録順に付与します。idを使ってログインユーザーの管理と単語の管理をしました。単語には(id,word,meaning)を入れてユーザーごとに単語の表示を行います。
ファイル分割
このプログラムを実行するsever.goのカレントディレクトリに'db'というファイルを置きました。その中にDBを扱うファイルを置きました。これを扱うには
package main
import(
"fmt"
"html/template"
"net/http"
//ファイル分割したモジュール
//DB関係
"wordapp/db"
)
'wordapp/db'は'パッケージ名/使いたいディレクトリ名'をimportします。パッケージ名はgo.modを作ったときの名前です。dbの中のファイルには
package db
とします。これで使えるようになります。
まとめ
上記のことを組み合わせることで今回のようなものを作ることができました。
そしてseverとMySQLを起動して使えるようになります。
http://localhost:8080/user-login
改善点も多くありますのでこれからも進めていきたいです。
参考にしたもの
GoとHTMLについて
【Go実践】フォームで入力された情報をデータベースに登録する
【Go実践】POSTされたデータを受け取って処理する ― 入力フォームと確認画面の作成
【Go実践】同一のテンプレートを使って新規登録画面と編集画面を実装する ― テンプレートの分岐処理
【Golang】MySQLの基本的な操作を行う
Go言語(golang) テンプレートの使い方
GoとMySQLについて
【Go実践】GoでMySQLを使おう(1) – ドライバのインストールからデータベース接続まで
GO言語(golang)のデータベース(MariaDB・MySQL)操作(1)/database/sqlで最低限のクエリ
go言語 mysqlに接続してinsertを実行する
Go言語でMySQL の基本的操作(SELECT、UPDATE、INSERT)を行う
GoでSQLのSELECTをする
Goについて
nilとの付き合い方(panic: runtime error: invalid memory address or nil pointer dereference)
golang 文字列→数値、数値→文字列変換
[Go言語] ファイル分割とローカルパッケージ