Gin
httprouterはgo製Webフレームワークに使われている。
型のめも
gin.H
type H map[string]interface{}
routerのグルーピング
code:go
func main() {
router := gin.Default()
// Simple group: v1
v1 := router.Group("/v1")
{
v1.POST("/login", loginEndpoint)
v1.POST("/submit", submitEndpoint)
v1.POST("/read", readEndpoint)
}
}
ミドルウェア
r.GET("/benchmark", MyBenchLogger(), benchEndpoint)
個別にミドルウェアを設定できる。
ミドルウェアはUseした順番に実行される。
以下の用に順番い呼び出される。
ミドルウェア1
ctx.Next()
ミドルウェア2
ctx.Next()
ミドルウェア3
ミドルウェア2
ミドルウェア1
Validation
validateとbindingのタグ名が異なるだけだと思う
code:validation
# go-playground/validatorではvalidate
validate:"required"
# ginではbindingを指定する
binding:"required"`
go-playground/validatorを使用しているみたい
structや[]もvalidateできるようだ。
リファレンス
c.ShouldBindQuery
GET qurery parameterのbind
Dive
Bindのとき
[]で深くネストしているときに使用するのか。
Bind実装
code:go
func (c *Context) Bind(obj interface{}) error {
b := binding.Default(c.Request.Method, c.ContentType())
return c.MustBindWith(obj, b)
}
Shoud
400 statusコードを設定しない
独自エラーハンドリングする場合。
Bindは、MustBindWithが呼び出される400でエラーハンドリングされている。
bindの場合の内部実装
c.AbortWithError(http.StatusBadRequest, err) が呼び出されている
Like c.Bind() but this method does not set the response status code to 400 and abort if the json is not valid.
Formのbind
Multipart/Urlencoded binding
Ginのテスト
code:go
package main
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/stretchr/testify/assert"
)
func TestPingRoute(t *testing.T) {
router := setupRouter()
w := httptest.NewRecorder()
req, _ := http.NewRequest("GET", "/ping", nil)
router.ServeHTTP(w, req)
assert.Equal(t, 200, w.Code)
assert.Equal(t, "pong", w.Body.String())
}
httptest
w := httptest.NewRecorder()
ResponseRecoderを生成
http.ResponseWriterインターフェイスを満たしている、
WriteでBodyにbufを書き込み
ServeHTTP実装
Request
スケール
アプリケーションサーバーは不要
gin自体goroutineが入っている。
1リクエストが一つのgoroutineで実行される?
参考
traefik
dockerの負荷分散
go web framework benchmark
jobrunner
他、Go製のHTTPフレームワーク
echo
echoの場合、目的に応じてミドルウェアを導入
CRUD