ゆずめも

メモ的なブログです。主に勉強した事について書いてます。

Goのnet/httpパッケージを使ったAPI開発を素振りしてた

最近調査を兼ねてgolang触ってみてるのでメモがてらgoでのhttp処理の書き方をまとめる

Goのnet/httpパッケージの仕組み

まだ全然詳しくないので、雑に言うとhttp.Handlerを定義し、それをパスと関連を付ける事によってルーティングされて実行される

例えば

package main

import (
  "fmt"
  "net/http"
)

func main() {
  http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintln(w, "Hello World")
  })
  
  http.ListenAndServe(":8080", nil)
}

これでgo run等で実行すると以下のようにcurlで実行できるようになる

curl -v 'http://localhost:8080'

POST等の判別

リクエストのメソッド(GET, POST等)を判断するためにはhttp.RequestMethodプロパティを参照すればいい

例えばGETかそれ以外かを見分けるならこんな感じ

if r.Method == http.MethodGet {
  fmt.Fprintln(w, "Get Method")
} else {
  fmt.FPrintln(w, "Other Method")
}

POSTでForm valueを取得する

POSTメソッドにFormの形式で送る

package main

import (
    "fmt"
    "net/http"
)

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
            fmt.Fprintln(w, r.FormValue("nogizaka"))
    })

    http.ListenAndServe(":8000", nil)
}

これでcurlで"nogizaka=maiyan"をPOSTすると「mayiyan」が返ってくる

curl -v -X POST -F "nogizaka=maiyan" 'http://localhost:8000'

JSONをPOSTする

web application作ってるとよくあるjsonを投げて、それを解釈してJSONを返す*1

package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
)

// jsonのSchema
type InputJsonSchema struct {
    Name string `json:"name"`
}

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    // request bodyの読み取り
        b, err := ioutil.ReadAll(r.Body)
        if err != nil {
            fmt.Println("io error")
            return
        }

        // jsonのdecode
        jsonBytes := ([]byte)(b)
        data := new(InputJsonSchema)
        if err := json.Unmarshal(jsonBytes, data); err != nil {
            fmt.Println("JSON Unmarshal error:", err)
            return
        }
        fmt.Fprintln(w, data.Name)
    })

    http.ListenAndServe(":8000", nil)
}

これでcurlを投げるとnameプロパティに設定したものが返ってくる

curl -v -X POST -d '{"name": "乃木坂"}' 'http://localhost:8000'

まとめ的なもの

ちょこちょこ軽いapiなら'net/http'だけで作るみたいなの見たことあった気がしたので挑戦してみたけど、流石に何かしらweb framework入れて開発したほうがいい気はした

まだ配列操作*2とかDBへの処理軽く見ただけで実際に動かせてないのでそこらへんやったら何か作れそう

*1:Content-Typeはifで分けるだけっぽいので無視してる

*2:厳密にはスライス操作かな