はじめに
どうも!みなさんこんにちは!
Go言語楽しんでますか?
最近,Go言語を使ったとあるインターンに参加したのですが,
そこでnet/httpに取って代わるかもしれない
fasthttpというパケージに触れる機会があったので,
今回は対応表という形でまとめたいと思います.
fasthttpとは
go言語でHTTP通信を行うためのライブラリです.
go言語の標準パッケージではnet/httpがすでに用意されているのですが,
fasthttpでは標準パッケージを凌駕する処理の速さで一時期有名になりました.
公式のベンチマークでは,従来に比べ10倍の差がでたようです.
fasthttpのインストール
go get -u github.com/valyala/fasthttp
対応表
サーバの起動
net/http
package main
import (
"fmt"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Hello net/http!!")
}
func main() {
// "/"に対しての処理
http.HandleFunc("/", handler)
// 8080でサーバを起動
http.ListenAndServe(":8080", nil)
}
fasthttp
package main
import (
"fmt"
"github.com/valyala/fasthttp"
)
func handler(ctx *fasthttp.RequestCtx) {
fmt.Fprint("Hello fasthttp!!")
}
func main() {
requestHandler := func(ctx *fasthttp.RequestCtx) {
// ctx.Path()がnet/httpでいうr.URL.Pathにあたる
switch string(ctx.Path()) {
// "/"に対しての処理
case "/":
handler(ctx)
default:
ctx.Error("Unsupported path", fasthttp.StatusNotFound)
}
}
// 8080でサーバを起動
fasthttp.ListenAndServe(":8080", requestHandler)
}
エラーハンドリング
net/http
if err := http.ListenAndServe(":8080", nil); err != nil {
log.Fatal(err)
}
fasthttp
if err := fasthttp.ListenAndServe(":8080", requestHandler); err != nil {
log.Fatal(err)
}
クエリ
以下のURLのクエリからそれぞれの値を取得
http://localhost:8080?name=satto&age=24
net/http
func handler(w http.ResponseWriter, r *http.Request) {
// クエリはr.URL.Query().Get("key")で取得可能
name := r.URL.Query().Get("name")
age := r.URL.Query().Get("age")
fmt.Fprintf(w, "name: %s age: %s\n", name, age)
}
/*===============省略==================*/
fasthttp
func handler(ctx *fasthttp.RequestCtx) {
// クエリはctx.QueryArgs().Peek("key")で取得可能
// stringでアスキーコードを文字に変換
name := string(ctx.QueryArgs().Peek("name"))
age := string(ctx.QueryArgs().Peek("age"))
fmt.Fprintf(ctx, "name: %s age: %s\n", name, age)
}
/*===============省略==================*/
POST
JSONをPOSTするとJSONが返ってくる簡単なAPIサーバ
net/http
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
type Input struct {
In string
}
type Output struct {
Out string
}
func jsonHandleFunc(w http.ResponseWriter, r *http.Request) {
// outputの用意
output := Output{"( ・`ω・´)"}
outjson, err := json.Marshal(output)
if err != nil {
fmt.Println(err)
}
w.Header().Set("Content-Type", "application/json")
fmt.Fprint(w, string(outjson))
// POSTされたときの処理
// ボディーの中身をチェック
body, err := ioutil.ReadAll(r.Body)
if err != nil {
output.Out = err.Error()
fmt.Println(err.Error())
return
}
input := Input{}
// bodyの中身(JSON)をinputに流し込む
err = json.Unmarshal(body, &input)
if err != nil {
output.Out = err.Error()
fmt.Println(err.Error())
return
}
}
func main() {
// 例 localhost:8080/json にJSONをPOSTするとJSONが返ってくる
http.HandleFunc("/json", jsonHandleFunc)
// 8080でサーバを起動
http.ListenAndServe(":8080", nil)
}
fasthttp
package main
import (
"encoding/json"
"fmt"
"github.com/valyala/fasthttp"
)
type Input struct {
In string
}
type Output struct {
Out string
}
func jsonHandleFunc(ctx *fasthttp.RequestCtx) {
// outputの用意
output := Output{"( ・`ω・´)"}
// output用のJSON作成
outjson, err := json.Marshal(output)
if err != nil {
fmt.Println(err)
}
ctx.Response.Header.Set("Content-Type", "application/json")
fmt.Fprint(ctx, string(outjson))
// POSTされたときの処理
// ボディーの中身を取得
body := ctx.PostBody()
input := Input{}
// bodyの中身(JSON)をinputに流し込む
err = json.Unmarshal(body, &input)
if err != nil {
output.Out = err.Error()
fmt.Println(err.Error())
return
}
}
func main() {
requestHandler := func(ctx *fasthttp.RequestCtx) {
switch string(ctx.Path()) {
// 例 localhost:8080/json にJSONをPOSTするとJSONが返ってくる
case "/json":
jsonHandleFunc(ctx)
default:
ctx.Error("Unsupported path", fasthttp.StatusNotFound)
}
}
// 8080でサーバを起動
fasthttp.ListenAndServe(":8080", requestHandler)
}
実際にcurlで叩いてみる
$ curl -H "Content-type: application/json" -X POST -d '{"In": "(´・ω・`)"}' http://localhost:8080/json
結果
$ {"Out":"( ・`ω・´)"}
静的ファイル配信
ディレクトリ構造
.
├── main.go
└── static
└── index.html
http://localhost:8080 にアクセスするとstaticディレクトリのindex.htmlの内容が表示される
net/http
package main
import (
"net/http"
)
func main() {
// 静的ファイル配信
// カレントディレクトリにあるstaticの中身を配信
http.Handle("/", http.FileServer(http.Dir("static")))
// 8080でサーバを起動
http.ListenAndServe(":8080", nil)
}
fasthttp
package main
import (
"github.com/valyala/fasthttp"
)
func main() {
// fsは静的ファイルを配信するために必要な設定を表す
var fs fasthttp.FS
requestHandler := func(ctx *fasthttp.RequestCtx) {
switch string(ctx.Path()) {
case "/":
// カレントディレクトリにあるstaticのindex.htmlを配信
fs = fasthttp.FS{
Root: "./static",
// ファイルを指定してあげないと読み込まれない
IndexNames: []string{"index.html"},
}
default:
ctx.Error("Unsupported path", fasthttp.StatusNotFound)
}
// 静的ファイルを配信するためのリクエストハンドラを作成
fsHandler := fs.NewRequestHandler()
fsHandler(ctx)
}
// 8080でサーバを起動
fasthttp.ListenAndServe(":8080", requestHandler)
}
ステータスコード
ほとんど変わりません
| ステータスコード | fasthttp | net/http |
|---|---|---|
| 100 | fasthttp.StatusContinue | http.StatusContinue |
| 101 | fasthttp.StatusSwitchingProtocols | http.StatusSwitchingProtocols |
| 102 | fasthttp.StatusProcessing | http.StatusProcessing |
| 200 | fasthttp.StatusOK | http.StatusOK |
| 201 | fasthttp.StatusCreated | http.StatusCreated |
| 202 | fasthttp.StatusAccepted | http.StatusAccepted |
| 203 | fasthttp.StatusNonAuthoritativeInfo | http.StatusNonAuthoritativeInfo |
| 204 | fasthttp.StatusNoContent | http.StatusNoContent |
| 205 | fasthttp.StatusResetContent | http.StatusResetContent |
| 206 | fasthttp.StatusPartialContent | http.StatusPartialContent |
| 207 | fasthttp.StatusMultiStatus | http.StatusMultiStatus |
| 208 | fasthttp.StatusAlreadyReported | http.StatusAlreadyReported |
| 226 | fasthttp.StatusIMUsed | http.StatusIMUsed |
| 300 | fasthttp.StatusMultipleChoices | http.StatusMultipleChoices |
| 301 | fasthttp.StatusMovedPermanently | http.StatusMovedPermanently |
| 302 | fasthttp.StatusFound | http.StatusFound |
| 303 | fasthttp.StatusSeeOther | http.StatusSeeOther |
| 304 | fasthttp.StatusNotModified | http.StatusNotModified |
| 305 | fasthttp.StatusUseProxy | http.StatusUseProxy |
| 306 | fasthttp._ | |
| 307 | fasthttp.StatusTemporaryRedirect | http.StatusTemporaryRedirect |
| 308 | fasthttp.StatusPermanentRedirect | http.StatusPermanentRedirect |
| 400 | fasthttp.StatusBadRequest | http.StatusBadRequest |
| 401 | fasthttp.StatusUnauthorized | http.StatusUnauthorized |
| 402 | fasthttp.StatusPaymentRequired | http.StatusPaymentRequired |
| 403 | fasthttp.StatusForbidden | http.StatusForbidden |
| 404 | fasthttp.StatusNotFound | http.StatusNotFound |
| 405 | fasthttp.StatusMethodNotAllowed | http.StatusMethodNotAllowed |
| 406 | fasthttp.StatusNotAcceptable | http.StatusNotAcceptable |
| 407 | fasthttp.StatusProxyAuthRequired | http.StatusProxyAuthRequired |
| 408 | fasthttp.StatusRequestTimeout | http.StatusRequestTimeout |
| 409 | fasthttp.StatusConflict | http.StatusConflict |
| 410 | fasthttp.StatusGone | http.StatusGone |
| 411 | fasthttp.StatusLengthRequired | http.StatusLengthRequired |
| 412 | fasthttp.StatusPreconditionFailed | http.StatusPreconditionFailed |
| 413 | fasthttp.StatusRequestEntityTooLarge | http.StatusRequestEntityTooLarge |
| 414 | fasthttp.StatusRequestURITooLong | http.StatusRequestURITooLong |
| 415 | fasthttp.StatusUnsupportedMediaType | http.StatusUnsupportedMediaType |
| 416 | fasthttp.StatusRequestedRangeNotSatisfiable | http.StatusRequestedRangeNotSatisfiable |
| 417 | fasthttp.StatusExpectationFailed | http.StatusExpectationFailed |
| 418 | fasthttp.StatusTeapot | http.StatusTeapot |
| 422 | fasthttp.StatusUnprocessableEntity | http.StatusUnprocessableEntity |
| 423 | fasthttp.StatusLocked | http.StatusLocked |
| 424 | fasthttp.StatusFailedDependency | http.StatusFailedDependency |
| 426 | fasthttp.StatusUpgradeRequired | http.StatusUpgradeRequired |
| 428 | fasthttp.StatusPreconditionRequired | http.StatusPreconditionRequired |
| 429 | fasthttp.StatusTooManyRequests | http.StatusTooManyRequests |
| 431 | fasthttp.StatusRequestHeaderFieldsTooLarge | http.StatusRequestHeaderFieldsTooLarge |
| 451 | fasthttp.StatusUnavailableForLegalReasons | http.StatusUnavailableForLegalReasons |
| 500 | fasthttp.StatusInternalServerError | http.StatusInternalServerError |
| 501 | fasthttp.StatusNotImplemented | http.StatusNotImplemented |
| 502 | fasthttp.StatusBadGateway | http.StatusBadGateway |
| 503 | fasthttp.StatusServiceUnavailable | http.StatusServiceUnavailable |
| 504 | fasthttp.StatusGatewayTimeout | http.StatusGatewayTimeout |
| 505 | fasthttp.StatusHTTPVersionNotSupported | http.StatusHTTPVersionNotSupported |
| 506 | fasthttp.StatusVariantAlsoNegotiates | http.StatusVariantAlsoNegotiates |
| 507 | fasthttp.StatusInsufficientStorage | http.StatusInsufficientStorage |
| 508 | fasthttp.StatusLoopDetected | http.StatusLoopDetected |
| 510 | fasthttp.StatusNotExtended | http.StatusNotExtended |
| 511 | fasthttp.StatusNetworkAuthenticationRequired | http.StatusNetworkAuthenticationRequired |