引き続きTODOリストを作っていきます。
下記の書籍を参考にさせていただいています。
Goプログラミング実践入門 標準ライブラリでゼロからWebアプリを作る impress top gearシリーズ
- 作者:Sau Sheong Chang,武舎 広幸,阿部 和也,上西 昌弘
- 発売日: 2017/03/17
- メディア: Kindle版
ルーティング
/task
へのリクエストを、それぞれ対応するハンドラメソッドに渡します。
func main() { ... http.HandleFunc("/tasks", handleRequest) ... } func handleRequest(w http.ResponseWriter, r *http.Request) { w.Header().Set("Access-Control-Allow-Origin", "http://localhost:3000") w.Header().Set("Content-Type", "application/json") var err error switch r.Method { case "GET": err = handleGetAll(w, r) case "POST": err = handleStore(w, r) } if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } }
Method(GET/POST)で分岐しています。
GO言語標準だとどうにもこういう泥臭い書き方になる模様です。HTTPフレームワークを入れたい...。
Access-Control-Allow-Origin
ヘッダーの指定によって、フロントエンドにおけるCORSエラーを回避しています。
Jsonエンコーディング
encoding/json
という公式のJson処理用ライブラリを導入します。
structにアノテーションをつけて、jsonと相互変換した時のkey名を指定します。
type Task struct { Id int `json:"id"` Name string `json:"name"` Status int `json:"status"` }
一覧取得API
DBから取得し、ループ処理でstructに値を入れます。
func getTasks(limit int) (tasks []Task, err error) { rows, err := db.Query("SELECT id, name, status FROM tasks LIMIT ?", limit) defer rows.Close() if err != nil { fmt.Println(err.Error()) return } for rows.Next() { task := Task{} if err = rows.Scan(&task.Id, &task.Name, &task.Status); err != nil { return } tasks = append(tasks, task) } return }
関数型っぽいmap
とかは標準であるんでしょうか?
foreach
は、気分が良くはないですね。
jsonに変換して、レスポンスを返します。
func handleGetAll(w http.ResponseWriter, r *http.Request) (err error) { tasks, err := getTasks(30) json, _ := json.Marshal(tasks) w.Write(json) return }
作成API
リクエストのパース用にstructを用意します。
type StoreRequest struct { Name string `json:"name"` }
リクエストをjson decodeし、DBにINSERTします。
func storeTask(name string) (err error) { _, err = db.Exec("INSERT INTO tasks(name, status) VALUES (?, 0)", name) return } func handleStore(w http.ResponseWriter, r *http.Request) (err error) { var sr StoreRequest json.NewDecoder(r.Body).Decode(&sr) err = storeTask(sr.Name) return }
フロントエンドのAPI連携
一覧API連携部分は、vueと独立したjsモジュールとして用意します。
Fetch APIを利用しています。
export function getAll() { return fetch('http://localhost:8000/tasks'); } export function store(data) { return fetch('http://localhost:8000/tasks', { method: 'POST', body: JSON.stringify(data), }) }
あとは、前回作成したモックをこのモジュールを使うように書き直します。
まとめ
さくさくAPIを追加しました。
Goはあまりスマートに記述できている気がしていないですが...。
ルーティングを書くのが面倒になりそうなので、フレームワークを導入する予定です。