5.11. Eudore特性演示
特性演示
本部分主要展示Eudore主要特性,一些框架基本功能就不介绍了。
自定义Handler
eudore创新之一,赋予无限的Context扩展。
在其他框架处理函数都是一个固定的函数,而eudore几乎支持任意处理函数,只需要额外注册一下转换函数,将任意函数转换成eudore.HanderFunc对象即可,在基于路由匹配返回字符串的benckmark测试中,处理函数转换造成的性能丢失低于1%。
基于处理函数扩展机制,可以给处理请求的请求上下文添加任意函数。
可以使用eudore.DefaultHandlerExtend.ListExtendHandlerFun()函数查看内置支持的任意函数类型,如果是注册了不支持的处理函数类型会触发panic。
内置部分扩展处理函数类型:
func(func(eudore.ContextData)) eudore.HandlerFunc
func(eudore.handlerHTTP) eudore.HandlerFunc
func(http.Handler) eudore.HandlerFunc
func(func(http.ResponseWriter, *http.Request)) eudore.HandlerFunc
func(http.HandlerFunc) eudore.HandlerFunc
func(func()) eudore.HandlerFunc
func(func() interface {}) eudore.HandlerFunc
func(func() error) eudore.HandlerFunc
func(func(eudore.Context) error) eudore.HandlerFunc
func(func(eudore.Context) interface {}) eudore.HandlerFunc
func(func(eudore.Context) (interface {}, error)) eudore.HandlerFunc
func(func(eudore.Context, map[string]interface {}) (interface {}, error)) eudore.HandlerFunc
func(interface {}) eudore.HandlerFunc
func(func() string) eudore.HandlerFunc
func(fmt.Stringer) eudore.HandlerFunc
例如使用多种处理函数:
func main() {
app := eudore.NewApp()
app.AnyFunc("/*", func(ctx eudore.Context) {
ctx.WriteString("hello eudore")
})
// 如果返回error不为空,会返回500和请求id。
app.GetFunc("/check", func(ctx eudore.Context) error {
if len(ctx.GetQuery("value")) > 3 {
return fmt.Errorf("value is %s len great 3", ctx.GetQuery("value"))
}
return nil
})
// 对返回的数据调用Render格式化。
app.GetFunc("/data", func(ctx eudore.Context) interface{} {
return map[string]string{
"a": "1",
"b": "2",
}
})
app.Listen(":8080")
app.Run()
}
实现一个扩展函数
MyContext额外实现了一个Hello方法,然后使用eudore.RegisterHandlerFunc注册一个转换函数,转换函数要求参数是一个函数,返回参数是一个eudore.HandlerFunc。
闭包一个func(fn func(MyContext)) eudore.HandlerFunc
转换函数,就将MyContext类型处理函数转换成了eudore.HandlerFunc,然后就可以使用路由注册自己定义的处理函数。
例子:
package main
import (
"github.com/eudore/eudore"
"github.com/eudore/eudore/component/httptest"
)
// MyContext 定义新的请求上下文扩展。
type MyContext struct {
eudore.Context
}
func main() {
app := eudore.NewApp()
app.AddHandlerExtend(func(fn func(MyContext)) eudore.HandlerFunc {
return func(ctx eudore.Context) {
fn(MyContext{ctx})
}
})
app.GetFunc("/*", func(ctx MyContext) {
ctx.Hello()
})
client := httptest.NewClient(app)
client.NewRequest("GET", "/hello").Do().Out()
for client.Next() {
app.Error(client.Error())
}
client.Stop(0)
app.Run()
}
// Hello 方法返回hello。
func (ctx MyContext) Hello() {
ctx.WriteString("hello")
}
强大的路由
eudore创新之二,低逻辑复杂度实现强大的路由器。
零内存复制,高性能,Erouter匹配性能静态路由具有httprouter的70%,api匹配性能具有90%且内存分配仅消耗httprouter六分之一,但是具有严格路由匹配顺序、易扩展重写和代码复杂度低的特点。
eudore路由器分离出的erouter和httprouter性能测试结果:
goos: linux
goarch: amd64
pkg: github.com/eudore/web-framework-benchmark
BenchmarkHttprouterStatic-2 50000 25686 ns/op 1949 B/op 157 allocs/op
BenchmarkHttprouterGitHubAPI-2 30000 52997 ns/op 16571 B/op 370 allocs/op
BenchmarkHttprouterGplusAPI-2 500000 2570 ns/op 813 B/op 24 allocs/op
BenchmarkHttprouterParseAPI-2 500000 3791 ns/op 986 B/op 42 allocs/op
BenchmarkErouterRadixStatic-2 50000 34314 ns/op 1950 B/op 157 allocs/op
BenchmarkErouterRadixGitHubAPI-2 30000 57850 ns/op 2786 B/op 203 allocs/op
BenchmarkErouterRadixGplusAPI-2 500000 2468 ns/op 173 B/op 13 allocs/op
BenchmarkErouterRadixParseAPI-2 300000 4551 ns/op 323 B/op 26 allocs/op
BenchmarkErouterFullStatic-2 50000 34728 ns/op 1950 B/op 157 allocs/op
BenchmarkErouterFullGitHubAPI-2 30000 62151 ns/op 2787 B/op 203 allocs/op
BenchmarkErouterFullGplusAPI-2 500000 2570 ns/op 173 B/op 13 allocs/op
BenchmarkErouterFullParseAPI-2 300000 4362 ns/op 323 B/op 26 allocs/op
PASS
ok github.com/eudore/web-framework-benchmark 22.356s
具有匹配优先级,优先级为常量>变量>通配符。
app.AnyFunc("/*", func(ctx eudore.Context) {
ctx.WriteString("hello eudore core")
})
app.GetFunc("/get/:name", func(ctx eudore.Context) {
ctx.WriteString("get name: " + ctx.GetParam("name") + "\n")
})
app.GetFunc("/get/eudore", func(ctx eudore.Context) {
ctx.WriteString("get eudore\n")
})
Any方法不会覆盖其他方法,注册Any方法路由会注册全部方法。
app.GetFunc("/*path", func(ctx eudore.Context) {
ctx.WriteString("get path: /" + ctx.GetParam("path") + "\n")
})
// Any方法不会覆盖Get方法。
app.AnyFunc("/*path", func(ctx eudore.Context) {
ctx.WriteString("any path: /" + ctx.GetParam("path") + "\n")
})
支持路由器重新扩展,扩展对变量和通配符具有多种校验功能,通配符的校验和变量使用方法一样,都具有匹配优先级。
app := eudore.NewApp()
// 修改路由
app.Router = eudore.NewRouterFull()
eudore.Set(app.Router, "print", eudore.NewPrintFunc(app))
// 正则校验,相当于 regexp:^0.*$,是一个动态校验函数。
app.GetFunc("/get/:num|^0.*$", func(ctx eudore.Context) {
ctx.WriteString("first char is '0', num is: " + ctx.GetParam("num") + "\n")
})
// 动态校验函数,min闭包生成校验函数。
app.GetFunc("/get/:num|min:100", func(ctx eudore.Context) {
ctx.WriteString("num great 100, num is: " + ctx.GetParam("num") + "\n")
})
// 校验函数,使用校验函数isnum。
app.GetFunc("/get/:num|isnum", func(ctx eudore.Context) {
ctx.WriteString("isnum num is: " + ctx.GetParam("num") + "\n")
})
默认参数,路由路径使用空格分割,第一个字符串是路由路径,其他字符串是键值对的参数,当前用于模板、鉴权、熔断器。
app.AnyFunc("/* version=v0", func(ctx eudore.Context) {
fmt.Println("version:", ctx.GetParam("version"))
})
mvc支持
eudore控制器实现通过分析控制器得到路由方法路径和闭包执行控制器方法。
控制器接口需要实现初始化、释放和注入三个方法,初始化和释放完成控制器对象的初始化和释放过程,用于支持Before和After逻辑,Inject方法完成注入控制器路由到路由器中。
type Controller interface {
Init(Context) error
Release(Context) error
Inject(Controller, RouterMethod) error
}
eudore控制器实现Controller接口即可,默认内置ControllerBase、ControllerData、ControllerSingleton、ControllerView四种控制器。
- ControllerBase 为最基本的控制器,嵌入Context对象。
- ControllerData 在ControllerBase基础上使用嵌入ContextData对象。
- ControllerSingleton 作为一个单例控制器。
- ControllerView 在ControllerData基础上添加了默认模板参数,如果未写入响应数据,会使用Data属性来渲染响应数据。
例如创建一个简单的控制器:
type MyBaseController struct {
eudore.ControllerBase
}
func (ctl *MyBaseController) Any() {
ctl.Info("MyBaseController Any")
}
func (*MyBaseController) Get() interface{} {
return "get MyBaseController"
}
func (ctl *MyBaseController) GetInfoById() interface{} {
return ctl.GetParam("id")
}
func main() {
app := eudore.NewApp()
app.AddController(new(MyBaseController))
app.Listen(":8080")
app.Run()
}
控制器方法参数和请求上下文处理相同,也可以使用扩展类型。
http server解耦
eudore通过Server接口使用框架和http Server解耦,屏蔽各类Server实现的细节。
type Server interface {
SetHandler(http.Handler)
Serve(net.Listener) error
Shutdown(ctx context.Context) error
}
eudore拥有nethttp、eudore两种server,适配后fasthttp server需要分配大量内存且不常用,已删除相关,如果对server源码了解程度不高,建议使用app默认nethttp。
- nethttp server使用nethttp库启动服务,作为默认的server。
- eudore server是重新实现http/1.1的server,不保证可靠性。
// 使用eudore server
import (
"github.com/eudore/eudore"
eserver "github.com/eudore/eudore/component/server/eudore"
)
func main() {
app := eudore.NewApp(eserver.NewServer())
app.AnyFunc("/*", func(ctx eudore.Context) {
ctx.WriteString("start fasthttp server, this default page.\n")
ctx.WriteString("your path is " + ctx.Path())
})
app.Listen(":8088")
app.Run()
}
反馈和交流请加群组:QQ群373278915。
推荐文章: