React+axiosでPOST送信したデータをGoで受け取る

JSON形式かx-www-form-urlencoded形式かで、実装方法が異なるみたいです。

## バージョン
axios 0.24.0
go 1.16.6
react ^17.0.2

## それぞれの違い
### x-www-form-urlencoded形式
Content-Type　・・・　application/x-www-form-urlencoded
例　・・・　a=1&b=1（エンコード後：%20a%3D1%26b%3D1）
Go（サーバー側）の実装の際にr.Form.Get("name")、r.FormValue("name")、r.PostFormValue("name")のメソッドで送信されたデータを取り出せる。multipart/form-data形式もGoの実装方法は同じだが、key-value型のデータを送るのでapplication/x-www-form-urlencoded形式を使うことにする。

### JSON形式
Content-Type　・・・　application/json
例　・・・　{“a”:1,”b”:2}
Go（サーバー側）の実装の際に送信されたデータをデコードしてから取り出さなくてはならない。また、CORSの規定によりプリフライトが飛ぶので、ヘッダーに"Access-Control-Allow-Headers"と"Access-Control-Allow-Methods"を指定する必要がある。

## 実装例
### x-www-form-urlencoded形式

```js:クライアント側
import axios from "axios";

const App = () => {
  const handleSubmit = (event) => {
    event.preventDefault();
    // multipart/form-data形式のデータをapplication/x-www-form-urlencodedに変換
    const params = new URLSearchParams(new FormData(event.currentTarget));
    axios.post("http://localhost:8080", params);
  };

  return (
    <form onSubmit={(event) => handleSubmit(event)}>
      <label htmlFor="name">Name: </label>
      <br />
      <input type="text" id="name" name="name" />
      <br />
      <input type="submit" defaultValue={"Submit"} />
    </form>
  );
};

export default App;
```

```go:サーバー側
package main

import (
	"fmt"
	"log"
	"net/http"
)

func main() {
	h := func(w http.ResponseWriter, r *http.Request) {
                // オリジンが違う場合は設定する
		w.Header().Add("Access-Control-Allow-Origin", "http://localhost:3000")
                // FormValueメソッドで値を取り出せる
		fmt.Println("Name:", r.FormValue("name"))
	}

	http.HandleFunc("/", h)

	log.Fatal(http.ListenAndServe(":8080", nil))
}
```
### JSON形式
```js:クライアント側
import axios from "axios";

const App = () => {
  const handleSubmit = event => {
    event.preventDefault();
    const data = new FormData(event.currentTarget);
    axios.post('http://localhost:8080', {
      // axiosならJSONデータをリテラルで書ける
      name: data.get("name")
    })
  };

  return (
    <form onSubmit={event => handleSubmit(event)}>
      <label htmlFor="name">Name: </label>
      <br/>
      <input type="text" id="name" name="name"/>
      <br/>
      <input type="submit" defaultValue={"Submit"}/>
    </form>
  );
}

export default App;
```

```go:サーバー側
package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
)

type Param struct {
        // jsonで型定義
	Name string `json:"name"`
}

func main() {
	h := func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Access-Control-Allow-Origin", "http://localhost:3000")
                // プリフライト用。Content-Type（application/json含む）のヘッダーのリクエストを許可する。
		w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
                // プリフライト用。POSTメソッドのリクエストを許可する。
		w.Header().Set("Access-Control-Allow-Methods", "POST")

		if r.Method == "POST" {
                        // 変数を定義
			var param Param
                        // デコードして変数へ値を格納する
			if err := json.NewDecoder(r.Body).Decode(&param); err != nil {
				log.Fatal(err)
			}
			fmt.Println("Name:", param.Name)
		}
	}

	http.HandleFunc("/", h)

	log.Fatal(http.ListenAndServe(":8080", nil))
}
```

## 感想
x-www-form-urlencoded形式の方が実装が少し楽だけど、こっちでいいのかな・・・