大家好, 我是 老麦, 一个运维老兵, 现在专注于 Golang,DevOps,云原生基础设施建设。
我二次封装了一下字节跳动的 hertz 框架
项目地址: https://github.com/go-jarvis/hertzer
go to example/demo
go get -u github.com/go-jarvis/hertzer
func main() {
// define a server
s := &hertzer.Server{
Listen: ":8081",
}
// set server options, sam eas hertz
s.WithOptions(
server.WithBasePath("/api"),
server.WithIdleTimeout(10),
)
// add middlewares, same as the hertz
s.Use(prefunc(), postfunc())
// handle a router handler
s.Handle(&Ping{})
// Run server
if err := s.Run(); err != nil {
panic(err)
}
}
Main Router HandlerFunc
type Ping struct {
httpx.MethodPost `route:"/ping/:name"` // define method and path
// define the body
Name string `path:"name"`
Age int `query:"age"`
AuthToken string `header:"AuthToken"`
Address Address `json:"address"`
Score int `json:"score" form:"score"`
}
// Handle method must exists.
// reqeust data will be binded into p automaticly.
// it can be used directly.
func (p *Ping) Handle(ctx context.Context, arc *app.RequestContext) (any, error) {
fmt.Println(p.Address)
ret := resp.NewStatusResponse(consts.StatusAccepted, *p)
return ret, nil
}
So that, the default handler will be like:
// r.Handle(httpMethod, relativePath string, handlers ...app.HandlerFunc)
r.Handle("POST","/ping/:name", handler)
Add the PreHandlers
and PostHandlers
to combine the HandlerFunc Chain. NOTE: PreHandlers
and PostHandlers
as optional.
func (Ping) PreHandlers() []app.HandlerFunc {
return []app.HandlerFunc{
prefunc(),
}
}
func (Ping) PostHandlers() []app.HandlerFunc {
return []app.HandlerFunc{
postfunc(),
}
}
The Registered Router will be like
// r.Handle(httpMethod, relativePath string, handlers ...app.HandlerFunc)
r.Handle("POST","/ping/:name", [pre...,] handler, [post...])
As metioned before, the RouterGroups like the carriages of a train. They are not only mounted one by one, and but also can be mounted to any RouterGroup.
NOTE: The Mounted Ring is forbidden. And Directed Acyclic Graph(DAG)
of RouterGroups are required.
v1:=hertzer.NewRouterGroup(v1)
to create a new RouterGroupv2.AddGroup(v2)
to add children RouterGroup(s).// define a server
s := &hertzer.Server{
Listen: ":8081",
}
// define Router Groups
v1 := hertzer.NewRouterGroup("/v1")
v1.Handle(&Ping{})
v2 := hertzer.NewRouterGroup("/v2")
// mount children RouterGroup(s)
s.AddGroup(v1)
v1.AddGroup(v2)
s.AddGroup(v2)
By default,
func (p *Ping) Handle(...) (result any, err error) {}
Typically, the response will be
result
"err.Error()
"the 3rd
response is special, Router Binding error. + status code = 400 // StatusBadRequest + the data is actual value of binding error
However, you may use resp.NewStatusResponse
to set the HTTP Status Code whatever you need.
// define
func NewStatusResponse(code int, meta interface{}) StatusResponse {
return &statusResponse{
code: code,
meta: meta,
}
}
// usage
ret := resp.NewStatusResponse(consts.StatusBadGateway, *p)
return ret, nil
By the way, you can use errors.New
to create a status error.
// define
func New(err error, meta any) *StatusError {
return &StatusError{
Err: err,
Meta: meta,
Message: "",
}
}
// usage
serr := errors.New(err, *p)
serr = serr.SetMessage("Error Message")
By default the Message
will be the HTTP Status Message/Define if you don't SetMessage