Open4
go で API サーバを作る
完成形
package main
import (
"fmt"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Println("hello world")
}
func main(){
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
説明
(w http.ResponseWriter, r *http.Request) を受け取る関数を作成し HandleFunc に設定する。
この作成した関数がリクエストパスごとに処理を呼び出す。
定義ができたら ListenAndServe でサーバを起動する
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Println("hello world")
}
func main(){
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
Jsonを返却したい場合
返却したいJsonの構造体を作っておく
type User struct {
Id string `json:"id"`
Name string `json:"name"`
}
処理としては2つ
- 構造体をJsonにマーシャルする
- Json を ResponseWriter のbodyに書き込む
func handler(w http.ResponseWriter, r *http.Request) {
// レスポンス用の構造体を作成
user := User{
Id: "1",
Name: "AAA",
}
// Jsonに変換
_json, err := json.Marshal(user)
// 変換に失敗したらエラーとする
if err != nil {
http.Error(w, err.Error(), 500)
return
}
// 変換したJsonをbodyに書き込む
w.WriteHeader(http.StatusOK)
w.Write(_json)
}
ここまでは標準ライブラリである net/http
しか使ってなかった。
下記のようにリクエストパスに任意の値を受け取って、その値を取り回すといったことをするにはひと手間かかる
http.HandleFunc("/{ID}/name", handler)
やりたい場合、URLを切り取ってなんとかするしかない
userId := strings.TrimSuffix(r.URL.Path, "/name")
gorilla/mux
ルーティングだけをライブラリ使いたくなったので gorilla/mux
を使う
gorilla/mux
機能については少し古いけど下記記事に簡単な使い方がまとまっている
リクエストパスの値を使う方法
// gorilla/muxのRouterインスタンスを生成
r := mux.NewRouter()
r.HandleFunc("/{ID}/name", handler)
func handler(w http.ResponseWriter, r *http.Request) {
// ライブラリの関数を使うと取得可能
vars := mux.Vars(r)
id := vars["ID"]
}
クエリパラメータを設定する方法
r := mux.NewRouter()
// /name?id=xxx だった場合handlerが呼ばれる
r.HandleFunc("/name", handler) .Queries("id", "{id}")
ハマったこと
複数のクエリパラメータを使う場合、それぞれでQueriesを定義する必要がある
/name?id=xxx&age=yyy というリクエストと /name?id=xxx を両方使われる場合
// NG
r := mux.NewRouter()
// /name?id=xxx だった場合handlerが呼ばれる
r.HandleFunc("/name", handler) .Queries("id", "{id}").Queries("age", "{age}")
このように定義しておけば両方のパターンに対応できそうだけどできないみたい。
Queries で定義した組み合わせのみを条件としてhandlerが呼ばれるみたい。
// OK
r := mux.NewRouter()
// /name?id=xxx だった場合handlerが呼ばれる
r.HandleFunc("/name", handler) .Queries("id", "{id}").Queries("age", "{age}")
r.HandleFunc("/name", handler) .Queries("id", "{id}")
これで /name?id=xxx&age=yyy と /name?id=xxx というリクエストを両方handlerへ流すことができるようになる