karasuex54’s blog

プログラミングよりイリヤの方が好き

二郎的なサムシング

本記事は「UEC Advent Calendar 2019」15日目の記事です.
昨日はおひげPさんの記事でした.

blog.mbsoftware.tokyo

これでみなさんも深層学習の準備ができたので
f:id:karasuex54:20191214234957j:plain
なんとかできそうですね!

はじめに

はじめましての方は初めまして.僕は一類MIのB4のからすさんです.卒論が近くてボスに「君は文章書くのが苦手だから心配だよ」ってご心配かけてしまって泣きそうです;;.


みなさん二郎って知ってますか?(画像は前に府中二郎で撮ってきたもの)
f:id:karasuex54:20191213024155j:plain
具体的な二郎の内容は延べませんが,二郎のwebアプリってあるといいなーって思いました.どんな機能があるといい...?
・現在位置から最寄りの二郎店までの距離
・店舗ごとの掲示
...今の自分の実力で作れそうな範囲で考えてみました.

ちなみに,今回のwebアプリ作るのにGo言語,Go言語のWebフレームワークのginとDBはSQLite3を用いました.


この記事では制作の過程ではなく,初歩的な内容を書いてます.


初めてのGo言語とwebアプリ制作でしたので間違ってるところも多いと思いますが温かい目で見て頂ければ幸いです.
ソースコード活動記録?はこちらです.下の内容すっとばしたい方向けなのでどうぞ.

環境

Windows 10 Home
go version go1.13.4 windows/amd64
SQLite version 3.28.0

基本

基本的なことを書いていきたいと思います.

ひな形を作ろう!

Go / Gin で超簡単なWebアプリを作る - Qiita を参考にまずひな形を作って,それにいろいろと付け足していこうと思います.
main.goファイルとindex.htmlファイルを以下の作ります.(index.htmlmain.go内のrouter.LoadHTMLGlob("templates/*.html")で場所を指定するのでそこに作っておいてください.)

main.go

package main

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

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

    router.GET("/", func(ctx *gin.Context){
        ctx.HTML(200, "index.html", gin.H{})
    })

    router.Run()
}

index.html

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>Sample App</title>
</head>
<body>
    <h1>Hello World!!!</h1>
</body>
</html>

go run main.goで起動し f:id:karasuex54:20191214223231p:plain
ブラウザでhttp://localhost:8080/を表示すると f:id:karasuex54:20191214223405p:plain
上のように表示されたかと思います.
これでひな形(と動作確認)ができました.

次からはGoとhtmlとの挙動を見ていきたいと思います.

aタグ

index.html

<a href="/test">ここをクリック</a>

を追加しこれをクリックするとどうなるかを見ていきます.
main.goを起動した後に「ここをクリック」を押したら

404 page not found

と表示されたかと思います.
index.htmlからmain.goに「/testだお~」って送ったけども無いものは無いんで✋( ͡° ͜ʖ ͡°)
無かったなら作ればいい!ってことなのでmain.go内のmain関数内に

router.GET("/test", func(ctx *gin.Context){
    fmt.Println("クリックされたお")
    ctx.HTML(200, "index.html", gin.H{})
})

import "fmt"も忘れずに書きます.そして先ほどのタグをクリックすると f:id:karasuex54:20191214234530p:plain (ターミナルの方で)「クリックされたお」が表示され,ブラウザではindex.htmlが表示されたのではないかと思います.
先ほどの追加した

ctx.HTML(200, "index.html", gin.H{})

index.htmlを別の(例えば)hoge.htmlにするとhoge.htmlを表示させることができます.
200に関しては勉強不足なのであまり触れれないです.

gin.H{}って?

上の

ctx.HTML(200, "index.html", gin.H{})

で「gin.H{}ってなんぞや?」ってなりますよね.(なりますよね.)
簡単に説明するとhtml側に送る変数の中身です.
main.go内で

router.GET("/test", func(ctx *gin.Context){
    ctx.HTML(200, "index.html", gin.H{
        "text" : "クリックされたお",
        "number" : 16,
    })
})

index.html

<a href="/test">ここをクリック</a>
<p>{{.text}}</p>
<p>{{.number}}</p>

と追加しときます.先ほどと同様にクリックすると
f:id:karasuex54:20191215000706p:plain
↓↓↓↓↓↓↓↓
f:id:karasuex54:20191215000758p:plain
と表示させることができました.
もう少し詳しい話は

Gin(Golang)におけるHTMLテンプレート記述方法 - Qiita

を参考にするといいと思います.

リクエストの話

GETリクエストとPOSTリクエストの話を同時にしたいと思います.
index.html

<p>GET</p>
<form method="GET" action="/">
    <input type="text" name="get_text">
    <p><input type="submit"></p>
</form>
ここに入力した文字が出力されるよ「{{.get_text}}」
<p>POST</p>
<form method="POST" action="/">
    <input type="text" name="post_text">
    <p><input type="submit"></p>
</form>
ここに入力された文字が出力されるよ「{{.post_text}}」

main.go

router.GET("/", func(ctx *gin.Context){
    text := ctx.Query("get_text")
    ctx.HTML(200, "index.html", gin.H{
        "get_text" : text,
    })
})
router.POST("/", func(ctx *gin.Context){
    text := ctx.PostForm("post_text")
    ctx.HTML(200, "index.html", gin.H{
        "post_text" : text,
    })
})

としてください.
起動すると
f:id:karasuex54:20191215051550p:plain
method="GET"formで入力すると
f:id:karasuex54:20191215051910p:plain
URLを見てみると
f:id:karasuex54:20191215051928p:plain
name="get_text"としてたので/?get_text=hogehogeとなってますね.
GETリクエストされた後のmain.goではtext := ctx.Query("get_text")で値を取得していきます.
POSTの方も同様にURLには表示されませんが,text := ctx.PostForm("post_text")で取得してることがわかりますね.

データベースの話

Go言語のORMであるGORMを使ってSQLiteを操作しています.
まずはテーブルを作りたいので,例として以下のようなのを目指そうと思います.
f:id:karasuex54:20191215054129p:plain
main.goで構造体を次のように定義します.

type Student struct {
     gorm.Model
     Name string
     Num int
     Units int
     Gpa float64
}

テーブル名は構造体名が複数形になるのでStudentsになり,gorm.Modelにはid,created_at,updated_at,deleted_atのカラムが備わってます.
続いてmain.go内でDBを作ります.

func dbInit() {
    db, err := gorm.Open("sqlite3", "test.db")
    db.AutoMigrate(&Student{})
    defer db.Close()
}

gorm.Openの第二引数で作成するDBの名前,db.AutoMigrate()で構造体からテーブルを作成します.
次に値を入れてみましょう.

func dbinsert(){
    db, err := gorm.Open("sqlite3", "test.db")
    db.Create(&Student{Name: "からすさん", Num: 16000000, Units: 108, Gpa: 1.6357})
    defer db.Close()
}

やばいっすね...db.Create()で構造体とその中身の入ってるもので挿入してくれるみたいです.

まとめ

「これさえあればできる!」の(たぶん)最低限な内容を書いてみました.

さいごに

ボスの口癖に「違うよ」ってのがあります.(たぶん違います.)
読んでいただいた方の多くに「違うよ」って思うところがあったかと思いますが,後でこっそりと教えてくれると嬉しかったりします.
明日は mu_uec さんです.布教活動をされるみたいですけど技術系ではないって言ってるのが逆に怖いですね...((((;゚Д゚))))