Go言語のechoフレームワークを使用してAPIサーバーを立てる方法（入門）

Go言語にて、echoを使用してAPIサーバーを立てる方法を解説します

## インストール
以下のコマンドでインストール

```
go get github.com/labstack/echo/v4
```

## GetのAPIを実装する
GetのAPIを実装したmain.goを作成

```main.go
package main

import (
	"net/http"

	"github.com/labstack/echo/v4"
	"github.com/labstack/echo/v4/middleware"
)

func main() {
	// echoインスタンスを生成
	e := echo.New()

	// Middleware
	// httpリクエストの情報をログに表示
	e.Use(middleware.Logger())
	// パニックを回復し、スタックトレースを表示
	e.Use(middleware.Recover())

	// ルーティング
	e.GET("/", getSample)

	// サーバーをスタートさせる
	// ポート番号は引数で指定できる
	e.Logger.Fatal(e.Start(":8080"))
}

// Get API
func getSample(c echo.Context) error {
	return c.String(http.StatusOK, "Get!")
}
```

起動

```
go run main.go

   ____    __
  / __/___/ /  ___
 / _// __/ _ \/ _ \
/___/\__/_//_/\___/ v4.5.0
High performance, minimalist Go web framework
https://echo.labstack.com
____________________________________O/_______
                                    O\
⇨ http server started on [::]:8080
```

curlで確認

```
curl 'http://localhost:8080/'
```

以下がレスポンスとして返却されたらOK

```
Get!
```

## PostのAPIを実装する
Postの実装は以下の記述を追加

```
// mainメソッドのルーティングに追加
e.POST("/post", postSample)

// mainメソッド外に追加
// Post API
func postSample(c echo.Context) error {
	// Postの処理
	return c.String(http.StatusOK, "Post!")
}
```

curlで確認

```
curl -X POST 'http://localhost:8080/post'
```

以下がレスポンスとして返却されたらOK

```
Post!
```

### パラメーターを受け取る方法
URLパラメーターを受け取る場合は `Param` を使う 

```
// mainメソッドのルーティングききに追加
e.POST("/post/:id", postSample)

// mainメソッド外に追加
func postSample(c echo.Context) error {
	id, _ := strconv.Atoi(c.Param("id"))
	msg := fmt.Sprintf("url param %v", id)
	return c.String(http.StatusOK, msg)
}
```

また、クエリパラメーターを受け取る場合は `QueryParam` を使う

```
hoge := c.QueryParam("hoge")
```

curlで確認。レスポンスにURLパラメーターで渡したIDが確認できる

```
$ curl -X POST 'http://localhost:8080/post/1'
url param 1
```

### リクエストボディを受け取る方法
ボディとして渡されるjsonに合わせて構造体を用意して、`Bind`メソッドを使って受け取る

```
// 受け取るための構造体
type post struct {
	ID   int    `json:"id"`
	Name string `json:"name"`
}

// mainメソッドのルーティングに追加
e.POST("/post/:id", postSample)

// Handler
func postSample(c echo.Context) error {
	p := new(post)
	if err := c.Bind(p); err != nil {
		log.Printf("err %v", err.Error())
		return c.String(http.StatusInternalServerError, "Error!")
	}

	// URLパラメーターはBindで入らない
	id, err := strconv.Atoi(c.Param("id"))
	if err != nil {
		log.Printf("err %v", err.Error())
		return c.String(http.StatusInternalServerError, "Error!")
	}
	p.ID = id
	msg := fmt.Sprintf("id: %v, name %v", p.ID, p.Name)
	return c.String(http.StatusOK, msg)
}
```

curlで確認。レスポンスに送信したパラメーターが出力されている

```
$ curl -X POST -H 'Content-Type: application/json' -d '{"Name":"taro"}' localhost:8080/post/1
id: 1, name taro
```

## Put, Deleteの場合
Put, Deleteに関しても以下のようにルーティングを定義して関数を追加することで実装可能

```
e.PUT("/put", putSample)
e.DELETE("/delete", deleteSample)
```

## レスポンスの返却方法
レスポンスは、return部分にステータスコードと返却する内容を指定する
単純な文字列を返却する場合は、 `String` を使う


```
return c.String(http.StatusOK, "Get!")
```

JSONを返却したい場合は、 `JSON` を使う

```
// 構造体
type post struct {
	ID   int    `json:"id"`
	Name string `json:"name"`
}


// ルーティング(main内)
e.GET("/sample", getResponseSample)

// Handler
func getResponseSample(c echo.Context) error {
	p := &post{
		ID:   1,
		Name: "taro",
	}
	return c.JSON(http.StatusOK, p)
}
```

## 出典
- echo リファレンス
    - https://echo.labstack.com/
- labstack/echo
    - https://github.com/labstack/echo