beego中的中间件实现及go中的修饰器

这里说的中间件是指在接收到用户消息,先进行一系列的预处理,再交给实际的http.Handler去处理。
beego通过修饰器的方式实现pipeline的中间件。

// MiddleWare function for http.Handler
type MiddleWare func(http.Handler) http.Handler
// Run beego application.
func (app *App) Run(mws ...MiddleWare) {
    ......
    app.Server.Handler = app.Handlers
        for i := len(mws) - 1; i >= 0; i-- {
            if mws[i] == nil {
                continue
            }
            app.Server.Handler = mws[i](app.Server.Handler)
        }
    ......
}

修饰器是一种常见的设计模式,是面向对象编程领域中,一种动态地往一个类中添加新的行为的设计模式。就功能而言,修饰模式比生成子类更为灵活,可以给某个对象而不是整个类添加一些功能。
原理是增加一个修饰类包裹原来的类,修饰类可以添加一些新的功能,不需要用到新功能的地方,直接调用原来类中的方法。
go中没有类的概念,通过结构体成员嵌套直接可以使用成员的方法,并用该结构体实现新的方法。

// tcpKeepAliveListener sets TCP keep-alive timeouts on accepted
// connections. It's used by ListenAndServe and ListenAndServeTLS so
// dead TCP connections (e.g. closing laptop mid-download) eventually
// go away.
type tcpKeepAliveListener struct {
	*net.TCPListener
}

// 对AcceptTCP()返回的连接,进行一些设置,再返回修改后的连接。
func (ln tcpKeepAliveListener) Accept() (net.Conn, error) {
	tc, err := ln.AcceptTCP()
	if err != nil {
		return nil, err
	}
	tc.SetKeepAlive(true)
	tc.SetKeepAlivePeriod(3 * time.Minute)
	return tc, nil
}

// AcceptTCP accepts the next incoming call and returns the new
// connection.
func (l *TCPListener) AcceptTCP() (*TCPConn, error) {
	if !l.ok() {
		return nil, syscall.EINVAL
	}
	c, err := l.accept()
	if err != nil {
		return nil, &OpError{Op: "accept", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
	}
	return c, nil
}

在go中,函数是第一类的,所以也可以包裹函数,实现对函数的修饰。修饰器是在运行时动态增加对象的行为,在执行包裹对象的前后执行特定的逻辑。

//服务器统一出错处理。对实际执行业务逻辑的handler函数进行包裹,统一处理返回的err。
type Handler func(http.ResponseWriter, *http.Request) error

func ErrWrapper(handler Handler) func(http.ResponseWriter, *http.Request) {
	return func(writer http.ResponseWriter, request *http.Request) {
		err := handler(writer, request)
		if err != nil {
			log.Printf("Error occurred "+
				"handling request: %s",
				err.Error())
			code := http.StatusOK
			switch {
			case os.IsNotExist(err):
				code = http.StatusNotFound
			case os.IsPermission(err):
				code = http.StatusForbidden
			default:
				code = http.StatusInternalServerError
			}
			http.Error(writer,
				http.StatusText(code), code)
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值