Golangに入門したので簡単なREST API作ってHerokuにデプロイする

## はじめに

この度、[クリエイターズラボさん](https://www.creatorslab.jp/)のオンライン勉強会に参加させていただきまして、

Golangに入門しました！

Golangを書く楽しさに目覚めてしまったので、Golangで簡単なAPIを作ってHerokuにさくっとデプロイする手順をまとめておきます。

## Golangとは

公式ドキュメントは[こちら](https://golang.org/)

GolangはGoogleが開発してる言語で云々。。

というのはいくらでも説明されているので、本記事では省きます。

めっちゃ軽くてめっちゃ書きやすい言語なんだなあ〜って思ってます。

### Golangでできること

- WEBアプリケーション開発
- モバイルアプリケーション開発
- IoT分野での組み込み系システム開発

他にも様々な使われ方がされているらしいです。

本当になんでもできる。。

### Golangのメリット・デメリット

#### メリット

- 処理が高速
- コンパイルも早い
- シンプルな記述ができる
- ある程度制約があるため、チーム開発でも用いやすい

#### デメリット

- ジェネリックや継承など、言語仕様的に物足りない部分もある
- Golangエンジニアの数が少ない

## Golangでサーバーを立ててみる

軽量のWEBサーバー立てられるライブラリ
- echo (https://echo.labstack.com/guide)

上記のechoというライブラリを使えば、一瞬で簡単なREST APIが作れちゃいます。

echoライブラリをgogetしたら、下記のように記述するだけでサーバーが立てられます。

```go:main.go
import (
    "net/http"
	"os"
    
    "github.com/labstack/echo"
)

func main() {
    // サーバーのインスタンス作成
    e := echo.New()
    
    // ルーティング設定
    e.GET("/", helloworld)
    
    // サーバー起動
	e.Logger.Fatal(e.Start(":" + os.Getenv("PORT")))
}

func helloworld(c echo.Context) error {
    return c.String(HttpStatus.OK, "Hello, World")
}
```

起動コマンドは一応、こちらです。

```shell
go run main.go
```

これでサーバーを起動すれば、ルートにGETリクエストを投げるとHello, Worldという文字列（JSON）が返ってくるAPIが作れました！

## GolangでDB操作をする

DB操作に使えるライブラリ
- GORM (https://gorm.io/ja_JP/docs/index.html)

次に値をDBに保存、取得して表示する処理を追加していきましょう。

```go:main.go
import (
    "github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/sqlite"
    "github.com/labstack/echo"
)

type Content struct {
	gorm.Model
	Text    string `json:"text"`
}

// DBのインスタンスをグローバル変数に格納
var (
	db *gorm.DB
)

func main() {
    // DB接続処理
    var err error
    db, err = gorm.Open("sqlite3", "/tmp/gorm.db")
    if err != nil {
        panic("failed to connect database")
    }
    // サーバーが終了したらDB接続も終了する
    defer db.Close()
    
    // スキーマのマイグレーション
    db.AutoMigrate(&Content{})
    
    // レコード登録
    db.Create(&Content{Content: "Hello, World"})
    
    // レコード全取得
    db.Find(&Content)
}
```

GORMはORMなので、SQL文を書かなくてもDB操作をすることができます。

GORMを使えば上記のように、私のようなSQL初心者でも超簡単にDB操作できてしまいます。。すごい。。

これを上記のコードと組み合わせたコードがこちらです。

```go:main.go
import (
    "net/http"
	"os"
    
    "github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/sqlite"
    "github.com/labstack/echo"
)

type Content struct {
	gorm.Model
	Text    string `json:"text"`
}

// DBのインスタンスをグローバル変数に格納
var (
	db *gorm.DB
)

func main() {
    // DB接続処理
    var err error
    db, err = gorm.Open("sqlite3", "/tmp/gorm.db")
    if err != nil {
        panic("failed to connect database")
    }
    // サーバーが終了したらDB接続も終了する
    defer db.Close()
    
    // サーバーのインスタンス作成
    e := echo.New()
    
    // ルーティング設定
    e.GET("/contents", getAllContents)
    e.POST("/create", createContent)
    
    // サーバー起動
    e.Logger.Fatal(e.Start(":" + os.Getenv("PORT")))
}

func createContent(c echo.Content) error {
    // レコード登録
    db.Create(&Content{Text: "newText"})
    return c.String(http.StatusOK, "record created")
}

func getALlContent(c echo.Content) error {
    var content Content
    // contentテーブルのレコードを全件取得
    db.find(&content)
    // 取得したデータをJSONにして返却
    return c.JSON(http.StatusOK, content)
}
```

## 【下準備】Golang製のAPIをHerokuにデプロイする

herokuでgo apiをビルドするために必要なもの
- go.mod　→　バージョン管理
- Procfile　→　heroku独自のconfigファイル
- GitHubリポジトリ　→　herokuデプロイの際に必要

herokuでGo製のAPIを動かすためには、ローカルでは必要なかったファイルをいくつか作成する必要があります。

順番にみていきましょう。

### go.modについて

まずはgo.modと呼ばれる**Goのバージョン管理ライブラリ**を導入します。

これがないと、herokuにデプロイする際に、ビルドで失敗してしまいます。

go.modファイルを作成することで、ライブラリのバージョンを定義しておけるので、それによってheroku上のサーバーでビルドすることが可能になります。

go.modの使い方は[こちらの記事](https://blog.mmmcorp.co.jp/blog/2019/10/10/go-mod/)に詳しく載っています。

ざっくりいうと、プロジェクトのルートディレクトリで下記のコマンドを叩くだけです。

```zsh
go mod init
```

これでgo.modの準備は完了しました！

### Procfileについて

Procfileについては[公式ドキュメント](https://devcenter.heroku.com/articles/procfile)があります。

ざっくりいうと、**heroku上でアプリを動かすのに必要なファイル**です。

詳しい書き方までは今回調べませんでしたので、詳細はドキュメントをご覧ください。

今回はルートディレクトリ直下にProcfileを作成し、コンパイルしたファイルのパスを指定するのみです。

```Procfile:Procfile
web: bin/first_go_api(作成したgitリポジトリ名)
```

### GitHubリポジトリについて

GitHubについての詳しい説明は省きます。

herokuはGitHubのリポジトリを参照してデプロイを行うので、リポジトリ作成しようねって話みたいです！

上述した通り、リポジトリ名はProcfileで指定する必要があるので、わかりやすい名前を付けましょう。

## 【実作業】Golang製のAPIをHerokuにデプロイする

では実際にデプロイしていきます。

当記事はherokuの記事ではないので、詳細な手順はググってみてください。

一応、herokuの公式ドキュメントは[こちら](https://devcenter.heroku.com/categories/command-line)

heroku cliからデプロイするのが簡単かなあと思います。

Dockerで環境構築してても簡単にデプロイできるみたいです。

デプロイが終わったら、curlコマンドを叩いて確認してみましょう！

POSTメソッド（レコード登録）↓

```zsh
curl -X POST -H "Content-Type: application/json" -d '{"Text":"newText"}' https://<アプリのURL>/create
```

レスポンスは下記の通りです。

```zsh:response
"record created"
```

続いてGETメソッド（レコード取得）↓

```zsh
curl 'https://<アプリのURL>/contents'
```

レスポンスは下記の通りです。

```json:response
{
    "Value": {
        "ID": 1,
        "CreatedAt": "2020-04-19T00:05:09.494982+09:00",
        "UpdatedAt": "2020-04-19T00:05:09.494982+09:00",
        "DeletedAt": null,
        "Text": "newText",
    },
    "Error": null,
    "RowsAffected": 1
}
```

ちゃんと取れてますね。

## おわりに

お仕事ではJavaがメインですが、Goの書きやすさ、分かりやすさには感動しました。。

趣味のプロダクトは、バックエンドはnode.jsで書くことが多いですが、これからはGoも視野に入れて技術選択していきたいです。

また、2020/4/19現在から2020/5/31までの期間限定で、メルカリのGo学習教材が無料公開されています。

気になる方はぜひ覗いてみてください！！

[プログラミング言語Go完全入門](https://tech.mercari.com/entry/2020/03/17/120137)