labstack/echo 一個輕量、高效的 Golang
網頁框架,讓使用者非常容易的建立 RESTful API 伺服器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| package main import ( "net/http" "github.com/labstack/echo" ) func main() { e := echo.New() e.GET("/", func(c echo.Context) error { return c.String(http.StatusOK, "Hello, World!") }) e.Logger.Fatal(e.Start(":1323")) }
|
1 2 3 4 5 6 7
| $ go run main.go ⇛ http server started on [::]:1323 $ curl http://localhost:1323 Hello, World!
|
echo
的 API 非常容易的擴充,一個好的 RESTful API 應該有定義嚴謹的 Response 格式。雖然 echo
的回傳函式已經有提供 JSON(code int, i interface{}) error
的方式可以讓我們回傳 JSON 的格式。
1 2 3 4 5 6 7
| e.GET("/json", func(c echo.Context) error { return c.JSON(http.StatusOK, map[string]interface{}{ "message": "Hello, World", }) })
|
當 API 的數量慢慢的成長,遇到修改回傳格式時就會照成維護的成本大大增加,這時候 ehco
也提供了 Context
擴充的方式,讓我們透過加載客製的 middleware
方法來擴充 API 回傳的函式,再搭配依照 Google JSON Style Guide 的規範統一回傳的格式
1 2 3 4 5 6 7 8 9 10 11 12 13
| e.GET("/json2", func(c echo.Context) error { type Res struct { SuccessData Name string } res := &Res{} res.Name = "Cage" return c.(Ctx).Res(http.StatusOK).Data(res).Do() })
|
1 2 3 4 5 6 7
| { "apiVersion": "v1", "data": { "code": 0, "Name": "Cage" } }
|
1 2 3 4 5 6 7 8 9 10 11 12
| e.GET("/json3", func(c echo.Context) error { type Res struct { SuccessData } res := &Res{} res.Items = []interface{}{"Cage", "Sunrain"} return c.(Ctx).Res(http.StatusOK).Data(res).Do() })
|
1 2 3 4 5 6 7 8 9 10
| { "apiVersion": "v1", "data": { "code": 0, "items": [ "Cage", "Sunrain" ] } }
|
1 2
| return c.(Ctx).Res(http.StatusBadRequest).Error("message here").Code(4001).Do()
|
1 2 3 4 5 6 7
| { "apiVersion": "v1", "error": { "code": 4001, "message": "message here", } }
|
1 2 3 4
| erros := make([]interface{}, 1) erros[0] = "333" return c.(Ctx).Res(http.StatusBadRequest).Error("message here").Code(4001).Errors(erros).Do()
|
1 2 3 4 5 6 7 8 9 10
| { "apiVersion": "v1", "error": { "code": 4001, "message": "message here", "errors": [ "333" ] } }
|
How to custom context
main.go
1 2 3 4 5
| e.Use(func(next echo.HandlerFunc) echo.HandlerFunc { return func(c echo.Context) error { return next(Ctx{c}) } })
|
context/context.go
1 2 3 4 5 6 7 8 9 10 11 12 13
| type Ctx struct { echo.Context } func (c Ctx) Res(httpStatus int) *jsonCall { rs := &jsonCall{ c: echo.Context(c), httpStatus: httpStatus, } return rs } ...
|
使用自己的 Context
最核心的部份是定義一個 Struct
並將 echo
中的 echo.Context
嵌入其中,這時候使用 Golang
特有的方式來對這一個 Struct
進行 func
的擴充,再完善自定欺的 Context
後即是需在透過 middleware
的方式掛載到 echo
中, 這樣一來在所有的 API 路中由就可以透過型別轉換的方式來操作自己義定的方法。
Github
Repo Custom labstack/echo Context
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| $ glide i $ go run main.go ⇛ http server started on [::]:1323 $ curl http://localhost:1323/json {"message":"Hello, World"} $ curl http://localhost:1323/json2 {"apiVersion":"v1","data":{"code":0,"Name":"Cage"}} $ curl http://localhost:1323/json3 {"apiVersion":"v1","data":{"code":0,"items":["Cage","Sunrain"]}} $ curl http://localhost:1323/json4 {"apiVersion":"v1","error":{"code":400001,"message":"Bad request"}} $ curl http://localhost:1323/json5 {"apiVersion":"v1","error":{"code":400001,"message":"Bad request","errors":["333"]}} $ go test context/context_test.go ok command-line-arguments 0.010s
|