タイムアウト検証用のアプリケーションサーバをGo言語で実装しました

f:id:shogonir:20170829005326p:plain

目次

  1. この記事の目的
  2. Go言語でサーバをたてる
  3. URLのパスに応じて処理を行う
  4. その他の処理
  5. 最終的なコード
  6. まとめ

 

1. この記事の目的

この記事では簡単なアプリケーションサーバをGo言語で実装します。
例として、クエリストリングで指定した時間が経過したらレスポンスを返すサーバを実装します。
たまに欲しくなることがあったので実装してGitHubにあげました。

 

github.com

 

2. Go言語でサーバをたてる

Go言語でサーバアプリケーションを手軽に実装したい場合、net/httpを使うと簡単でした。
サーバを立ち上げ、立ち上げに失敗した場合にエラーメッセージを表示するには次のようにします。

 

package main

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

func main() {
  port := 7999
  
  err := http.ListenAndServe(":" + strconv.Itoa(port), nil)
  
  if err != nil {
    fmt.Println(err)
  }
}

 

http.ListenAndServe() を実行するだけで、サーバを構築することができます。
すでに7999番のポート番号が使われている際などに、エラーメッセージを出力して終了します。

今の所、正常にサーバが立ち上がっても、リクエストを処理できません。
次の段落では、特定のパスでリクエストがきた際に処理が実行されるように修正していきます。

 

3. URLのパスに応じて処理を行う

URLのパスに応じた処理を登録するには、http.HandleFunc() を用います。
第一引数にパスの文字列、第二引数に関数を渡すと、そのパスのリクエストがきた際に第二引数の関数が実行されます。

今回は /zzz/ というパスにリクエストがきた際に “ok” と返すように実装します。

 

package main

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

func handler(w http.ResponseWriter, r *http.Request) {
  fmt.Fprint(w, "ok")
}

func main() {

  port := 7999

  http.HandleFunc("/zzz/", handler)

  err := http.ListenAndServe(":" + strconv.Itoa(port), nil)
  if err != nil {
    fmt.Println(err)
  }
}

 

4. その他の処理

コマンドライン引数を受け取ってポート番号を指定できるようにするに、flagを使用しました。 PythonJavaでは少し煩わしく感じたコマンドライン引数受け取りですが、Goだと簡単だった印象です。

指定された時間スリープするために time を使用しました。
スリープする時間の指定方法が、 下記のようにコードに単位がかけるので読みやすく好印象です。

 

time.Sleep(time.Duration(msInt) * time.Millisecond)

 

5. 最終的なコード

最終的なコードは下記のようになりました。
まだBadRequestのステータスコードが200になっていますがご了承ください。

 

package main

import (
  "fmt"
  "time"
  "flag"
  "net/http"
  "strconv"
)

func handler(w http.ResponseWriter, r *http.Request) {
  ms := r.URL.Query().Get("ms")
  msInt, _ := strconv.Atoi(ms)
  if (msInt > 20000) {
    fmt.Fprint(w, "Bad Request")
  } else {
    time.Sleep(time.Duration(msInt) * time.Millisecond)
    fmt.Fprint(w, "Good morning.")
  }
}

func main() {

  port := flag.Int("port", 7999, "listen port number")
  flag.Parse()

  http.HandleFunc("/zzz/", handler)

  err := http.ListenAndServe(":" + strconv.Itoa(*port), nil)
  if err != nil {
    fmt.Println(err)
  }
}

 

6. まとめ

Go言語で簡単なサーバアプリケーションを実装しました。
ローカルで実行すると、localhost:7999/zzz/?ms=1000 などでリクエストすると動作が確認できると思います。

Go言語では簡単にサーバアプリケーションを構築できて驚きました。
今後はBadRequestのステータスコードを400にしたい。