Go lang入門 GinとGORMでWebApp

# Goを入門することにした
最近よく聞くGo言語。
私は、Ruby,Pythonなど動的言語ばかりでほぼ静的言語の経験はありません。
しかし、静的言語が書けることに憧れがあり何か静的言語やりたいなと思ってました。
Goは、シンプルで扱いやすそうであり、楽しいと聞いたので入門してみました。
## Goのインストール
環境はmacOSです。

```
brew install go
```

## Goの設定

```bash:~/.bash_profile
export GOPATH=${HOME}/go
export PATH=$GOPATH/bin:$PATH
```

```
go env
```

でGoの環境変数を参照することができます。

## 作業ディレクトリを作る

`~/go`を作り、src pkg binを`~/go/`以下に作る。

```
mkdir $GOPATH
cd $GOPATH
mkdir src pkg bin
```

## vim-goをインストール
Vimmer以外はこの手順をステップしてください。
NeoBundleではこのようにインストール

```vim:.vimrc
NeoBundle 'fatih/vim-go'
```
そして

```
:NeoBundleInstall
```
をして、再起動後

```
:GoInstallBinaries
```
をして、必要なパッケージをインストールします。

vim-goでは、
補完をしたり、
```:GoFmt```でコード整形されたり（保存時にも自動で整形される）、
```:GoRun```で実行できたりします。
## Hello,World!してみる
`~/go/src/hello.go`を作成する。

```go:hello.go
package main

import "fmt"

func main() {
        fmt.Printf("Hello,World!\n")
}
```

```go run hello.go```またはvimで```:GoRun```をすると
Hello,World!を実行する。
一行目の```package main```でパッケージ宣言をします。
三行目では、fmtパッケージをインポートして、
main()関数のなかで、Hello,World!を表示させる処理を書きます。
## 基本文法を学ぶ
http://gihyo.jp/dev/feature/01/go_4beginners/0002?page=1
を読んで最低限なところは学びました。

# とりあえずGoでWebをやってみたい
今回はginというGo製のWebフレームワークを使ってみます。
ORマッパーはGORMを使用。
## Ginフレームワークの特徴
軽量なフレームワーク。
Go製のフレームワークにはRevelなどフルスタックなフレームワークが存在しますが、今回は軽いものをサクッと作りたかったので、ginにしました。
[こちら](https://www.techempower.com/benchmarks/)によると、Ginが他のGoのWAFに比べてレスポンスの速度が早いらしいです。
## GORMの特徴
かなり高機能で、RubyのActiveRecordに似ている。
## Ginのインストール
```
go get github.com/gin-gonic/gin
```

## ブラウザにHello,World!してみる
`~/go/src`以下に作業用ディレクトリを作る。

```
mkdir ~/go/src/gin-first-app
```
`~/go/src/gin-first-app`以下のmain.goにコードを書く。

```go:main.go
package main

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

func main() {
        r := gin.Default()
        r.GET("/", func(c *gin.Context) {
                c.String(200, "Hello,World!")
        })
        r.Run()
}
```
そして、```go run main.go```して、
http://localhost:8080　に行くと、、、
<img width="359" alt="スクリーンショット 2018-06-11 20.54.37.png" src="https://qiita-image-store.s3.amazonaws.com/0/188304/04964319-b161-c1fe-8308-182558aed355.png">
Hello,World!されました。
## 簡単な名簿WebAppを作ってみた
こんな感じです。
![gin_people_app_2.gif](https://qiita-image-store.s3.amazonaws.com/0/188304/c4b30a45-07ab-c23c-44ce-d09b11ab45e5.gif)
名前と年齢を入力して、登録することができます。
###ORMマッパーGORMを使う
gormインストール

```
go get -u github.com/jinzhu/gorm
```
go-sqlite3もインストール

```
go get -u github.com/mattn/go-sqlite3
```

データベースの情報をHTMLに表示させたいので、作業ディレクトリ以下（gin-first-app）にtemplatesディレクトリを置きましょう。
そしてそれ以下にindex.tmplを作成してください。
### main.goを編集

```go:main.go
package main

import (
        "fmt"
        "strconv"
        "github.com/gin-gonic/gin"
        "github.com/jinzhu/gorm"
        _ "github.com/mattn/go-sqlite3"
        _ "net/http"
)

type Person struct {
        gorm.Model
        Name string
        Age  int
}

func db_init() {
        db, err := gorm.Open("sqlite3", "test.sqlite3")
        if err != nil {
                panic("failed to connect database\n")
        }

        db.AutoMigrate(&Person{})
}
func create(name string, age int) {
        db, err := gorm.Open("sqlite3", "test.sqlite3")
        if err != nil {
                panic("failed to connect database\n")
        }
        db.Create(&Person{Name: name, Age: age})
}
func get_all() []Person {
        db, err := gorm.Open("sqlite3", "test.sqlite3")
        if err != nil {
                panic("failed to connect database\n")
        }
        var people []Person
        db.Find(&people)
        return people

}
func main() {
        r := gin.Default()
        r.LoadHTMLGlob("templates/*")
        db_init()
        r.GET("/", func(c *gin.Context) {
                people := get_all()
                c.HTML(200, "index.tmpl", gin.H{
                        "people": people,
                })
        })
        r.POST("/new", func(c *gin.Context) {
                name := c.PostForm("name")
                age, _ := strconv.Atoi(c.PostForm("age"))
                create(name, age)
                c.Redirect(302, "/")
        })
        r.Run()
}

```

ポイント

- type Person structでTable構造を宣言
- db_init()でマイグレーション
- `/new`にポストされたname,ageのデータをcreate()関数に渡してレコードを追加する
- `/new`は最後`/`にリダイレクトする


### index.tmplを編集

```html:index.tmpl

<html>
<head>
    <title>The first app on Gin WAF </title>
</head>
<body>
    <h1> 一覧</h1>
<form method="post" action="/new">
    <p>名前<input type="text" name="name" size="30" placeholder="入力してください" ></p>
    <p>年齢<input type="number" name="age" ></p>
    <p><input type="submit" value="Send"></p>
</form>
<ul>
    {{ range .people }}
        <li>{{.Name}}さん{{.Age}}才</li>
    {{ end }}
</ul>
</body>
</html>
```
ポイント

- rangeで配列を繰り返ししている
- range ~ end の中ではドットにメンバ名を指定し表示することができる

# 感想 
昨日からGoを始めたので、ここはこんな書き方で大丈夫なのかな、、っていう不安が残ります。
最初は全然なれなくて書くことは面白くなかったけどじわじわ楽しくなってきました。
もっとスラスラ書きたいですね。
# 参考文献

http://gihyo.jp/dev/feature/01/go_4beginners

https://qiita.com/kent_ocean/items/6dc9b96db70b4a4c3fa5