Go + Vue.js でGETとPOSTをやってみる

#はじめに
この記事はGo lang 駆け出しによる駆け出し向けの記事になっていますので基本的なことしか書いておりません。


今回はGo言語とVueを使ってPOSTとGETでリクエストを投げてパラメータの受け渡しをやってみる。
なおGoのフレームワークとしてEchoを使っていく。

こんなやつ↓
<img width="450" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520167/932f14e0-5cf8-940b-a4ad-946c829ecdf4.gif"/>

今回のコードはgithubに(最下部掲載)


#Vue.js前準備
まずはvueのプロジェクト作成
次にaxiosを入れる。リクエストはaxiosを使って送る。

```
$vue create ~~
$cd ~~
$npm install --save axios vue-axios
```

#main.go側
作成したプロジェクトの中に**main.go**ファイルを作る

今回はechoを使っていくのでフレームワークを入れる

```
$go get -u github.com/labstack/echo
```


大体の流れ↓

CORSを忘れずに。

```go:main.go
package main

import (
	"net/http"
	"github.com/labstack/echo"
  	"github.com/labstack/echo/middleware"
)

func main(){
	e := echo.New()

	//CORSの設定(vueのプロジェクトをGOで立てたlocalサーバーで起動する時は不要)
	e.Use(middleware.CORS())

	// リクエストに対するHandler
	e.GET("/getTitle", getTitle)
	e.GET("/getName/:name", getName)
	e.POST("/postName", postName)
	e.POST("/postCompany", postCompany)

	// local サーバー
	e.Logger.Fatal(e.Start(":8000"))
}
```

各Handler定義

```go:main.go

// GETリクエスト
func getTitle(c echo.Context) error {
	return c.String(http.StatusOK, "New Game")
}

// パラメータ付きのGETリクエスト
func getName(c echo.Context) error {
	name := c.Param("name")
	return c.String(http.StatusOK, name)
}

// application/x-www-form-urlencoded データのPOSTリクエスト
func postName(c echo.Context) error {
	name := c.FormValue("name")
	return c.String(http.StatusOK, name)
}

//JSON受け取り用の構造体
type JsonParam struct {
	Company string `json:"company"`
	Works string `json:"works"`
}

// JSONデータのPOSTリクエスト
func postCompany(c echo.Context) error {
	param := new(JsonParam)
	//バインドしてJSON取得
	if err := c.Bind(param); err != nil {
		return err
	}
	//JSONを返す
	return c.JSON(http.StatusOK, param)
}
```

GETリクエストではurlに`/~~/:パラメータ名`とし、`Context.Param(パラメータ名)`とすることでURLに付加されたのパラメータを取得できる。

POSTでデータを取得する際にデータがform-urlencodedなのかJSONなのかで取得の仕方が変わってくる。
**form-urlencodedの場合**は`Context.FormValue(キー)`で取れる。
**JSONの場合**は先に**JSONの構造体を用意しておいて`Context.Bind(構造体)`で取れる。

これでバックエンド側の準備は完了
次にフロントのvue側を作っていく。

```
$go run main.go
```

今回はポート8000でローカルサーバーを起動させておく

#Vue.js側
適当にビューを作作成

```vue:App.vue
<template>
  <div id="app">
    <button @click="sendRequest">リクエスト送信</button>
    <h1>取得結果</h1>
    <p>GET(パラメータ無):<br/><strong>{{title}}</strong></p>
    <p>GET(パラメータ有):<br/><strong>{{name1}}</strong></p>
    <p>POST(form-urlencoded):<br/><strong>{{name2}}</strong></p>
    <p>POST(JSONデータ):<br/><strong>{{company}}</strong></p>
  </div>
</template>

<script>
//~~省略~~
  data:()=>{
    return{
      title:"",
      name1:"",
      name2:"",
      company:""
    }
  }
</script>
```

次にリクエストを送る関数を作成していく

```vue:App.vue
<script>
import axios from "axios"

//~~省略~~
  methods: {
    sendRequest: async function(){
      //パラメータ無しでGETリクエスト
      const getRequestNoParam = await axios.get("http://localhost:8000/getTitle")

      //パラメータ付きでGETリクエスト
      const getRequest = await axios.get("http://localhost:8000/getName/ひふみん")

      //application/x-www-form-urlencodedでデータを送信
      const params = new URLSearchParams();
      params.append("name","青葉");
      const postRequest = await axios.post("http://localhost:8000/postName",params)

      //JSONデータを送信(axiosはデフォルトでJSONを送信)
      const jsonPostRequest = await axios.post("http://localhost:8000/postCompany", {
        company: "Eagle Jump",
        works: "PECO"
      });

      //取得結果をviewに反映
      this.title = getRequestNoParam.data
      this.name1 = getRequest.data
      this.name2 = postRequest.data
      this.company = jsonPostRequest.data
    }
}
</script>
```

axiosはPOSTリクエストの時デフォルトでJSONを送信するようになっているのでform-urlencodedを使いたいときは`URLSearchParams`APIを使う。

これで完成!!
`npm run serve`使ってvueのローカルサーバー(localhost:8080)で起動させればリクエストの送受信ができるはず。

#VueプロジェクトをGoのローカルサーバーで動かす
上の場合はvueプロジェクトを`npm run serve`使って、vueのローカルサーバー(localhost:8080)で動かして、Goはlocalhost:8000で動かしていた。これだとクロスドメインでCORSの設定が必要になる。

そこで、最後におまけ的な感じでvueプロジェクトをGoで起動したローカルサーバーで動かしてみる。

まずはvueプロジェクトをビルドする。

```
$npm run build
```
うまく実行できると**distフォルダ**ができてるはず。
あとは、これをGoで動かすだけ。

main.goを以下のように修正

```go:main.go
func main(){
	e := echo.New()
	//CORSの設定(vueのプロジェクトをGOで立てたlocalサーバーで起動する時は不要)
	// e.Use(middleware.CORS())

	// npm run buildでビルドしたものをgoで起動  corsも不要になる
	//  /でアクセスしたときのルーティング設定
	e.Static("/", "dist/")

	// リクエストに対するHandler
	e.GET("/getTitle", getTitle)
	e.GET("/getName/:name", getName)
	e.POST("/postName", postName)
	e.POST("/postCompany", postCompany)

	// local サーバー
	e.Logger.Fatal(e.Start(":8000"))
}
```

当然だけどVue.js側のリクエストを送るときも以下のように省略できる。

```js:App.vue
//パラメータ無しでGETリクエスト 
- const getRequestNoParam = await axios.get("http://localhost:8000/getTitle")
+ const getRequestNoParam = await axios.get("/getTitle")
```

あとはサーバーを起動して

```
$go run main.go
```
localhost:8000にアクセスすれば別々に動かしていた時と同じように使える。



#おわり
GoとVueを使って簡単にAPIのやり取りができた！
Goって結構たのしいな。
AWSとかで動かしてみたい...

今回のコード[GitHub](https://github.com/SY-BETA/GoWithVue)からどうぞ


#参考
[公式ドキュメント](https://echo.labstack.com/guide/request)

@y_ussie 様 : [Go言語のWebフレームワーク「Echo」を使ってみる ②（リクエストパラメータの扱い)](https://qiita.com/y_ussie/items/2d397e70bfc38f75ca51#post-apihello-1)

@567000 様 : [Go(golang) echoとVue-cliをつなげる](https://qiita.com/567000/items/a912873f51ed5b430173)

ありがとうございました。