emahiro/b.log

Drastically Repeat Yourself !!!!

go ✕ ajaxを書いてみた

サマリ

goで簡易的なajax通信するアプリを作ったのでそのメモ

構成

環境

ディレクトリ構成

- src
  - app
    - main.go
    - handler
      - handler.go
    - render
      - render.go
- templates
  - index.tmpl

sampleコード

main.go

var port = "8080"
func main() {
    router := mux.NewRouter()
    router.HandleFunc("/", handler.Top).Methods("GET")
    {
        router.HandleFunc("/sample", handler.SamplePost).Methods("POST")
    }
    if err := http.ListenAndServe(fmt.Sprintf(":%s", port), router); err != nil {
        log.Fatalf("err: %v", err)
    }
}

handler/handler.go

func SamplePost(w http.ResponseWriter, r *http.Request) {
    // postのリクエストを処理する
  client := http.Client{}
  req, err := http.NewRequest("POST", "http://sample.com/create", nil)
    if err != nil {
        log.Fatalf("build request error. err: %v", err)
    }
    // form をparseする
    if err := r.ParseForm(); err != nil {
        log.Fatalf("parse form error. err: %v", err)
    }

    // 何かしらrequestのbodyにparseしたURLのパラメータを入れ込む処理か何かが入る
  /*
    何かしらの処理
  */
  
    resp, err := client.Do(req)
    if resp.Status != "200 OK" {
        log.Fatalf("http request failed. code: %v", resp.Status)
    }
  json.NewEncoder(w).Encode(&resp)
}

index.tmpl のjsの部分

var url = $("form").attr("action");
var p = $("form").serialize()
$.ajax({
  url: url,
  type: "post",
  data: p,
}).done(function (data) {
  res = JSON.parse(data);
  // responseで返ってきたjsonを◯◯する
}).fail(function (err) {
  console.log(err)
});

ハマったところ

requestはそのままparseする

簡易的なajaxなので今回はjqueryを使ってさらっと書いてますが、goでPOSTリクエストを受けて、serializedされたパラメータを url.Values 型として扱うためには、ポインタとして受け渡される http.Request をそのままparseします。

// form をparseする
    if err := r.ParseForm(); err != nil {
        log.Fatalf("parse form error. err: %v", err)
    }

http.Request の持つ関数の中に PostFrom というのがありますが、これは新しく空の url.Values を作るだけで、フロントからリクエストされたrequestをparseしてくれるわけではないです。

直感的な名前がついていたために、間違って使っていて、どうしてもrequestを一度でparseできないと悩んでしまっていました。

まとめ

validationとか一切考えない超簡易的なajaxを書いてみましたが、標準のライブラリしか使っていないのに、案外簡単に書けました。