// Implement http.Handler interface.
func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request)
中使用反射库调用了controller
//Invoke the request handler
var execController ControllerInterface
if routerInfo != nil && routerInfo.initialize != nil {
execController = routerInfo.initialize()
} else {
vc := reflect.New(runRouter)
var ok bool
execController, ok = vc.Interface().(ControllerInterface)
if !ok {
panic("controller is not ControllerInterface")
}
}
//call the controller init function
execController.Init(context, runRouter.Name(), runMethod, execController)
//call prepare function
execController.Prepare()
并调用ControllerInterface
的Render
方法。
//render template
if !context.ResponseWriter.Started && context.Output.Status == 0 {
if BConfig.WebConfig.AutoRender {
if err := execController.Render(); err != nil {
logs.Error(err)
}
}
}
用到一个bytes.Buffer
作为内存的缓存,看封装挺简单的。
func (c *Controller) renderTemplate() (bytes.Buffer, error) {
var buf bytes.Buffer
//略...
}
bytes.Buffer方法
调用的ExecuteViewPathTemplate
方法是线程安全的,A template will be executed safely in parallel.
// ExecuteViewPathTemplate applies the template with name and from specific viewPath to the specified data object,
// writing the output to wr.
// A template will be executed safely in parallel.
func ExecuteViewPathTemplate(wr io.Writer, name string, viewPath string, data interface{}) error {
if BConfig.RunMode == DEV {
templatesLock.RLock()
defer templatesLock.RUnlock()
}
//略...
}
看一下是如何达到安全的,使用到了templatesLock,读写锁sync.RWMutex
templatesLock sync.RWMutex
看一下RWMutex的设计,RWMutex包含了一把Mutex锁和四个int32值,其中Mutex锁用于写锁定,而读锁用的是atomic实现的。
type RWMutex struct {
w Mutex // held if there are pending writers
writerSem uint32 // semaphore for writers to wait for completing readers
readerSem uint32 // semaphore for readers to wait for completing writers
readerCount int32 // number of pending readers
readerWait int32 // number of departing readers
}
网友评论