Golang Martini Source Reading notes of Martini Core

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

Following a note on inject injection, one of the key cores of Martini was understood: Dependency Injection. Injects a callback function that is executed by the runtime for active invocation. This article is mainly annotated martini skeleton Martini.go implementation, the following first from a simple martini use instance, that is, to create a simplest HTTP server to start.


Martini uses a simple instance of the package main import "Github.com/go-martini/martini" Func Main () {   m: = Martini. Classic ()//Get a Martini instance   m.get ("/", func () string {//user custom routing Rule     return "Hello world!"   })   M.run ()//Run Server}


Package Martiniimport ("Log" "Net/http" "OS" "Reflect" "github.com/codegangsta/inject")//Martini represents the top Level Web application. Inject. Injector methods can be invoked to map services on a global level.type Martini struct {inject. Injector//Injection tool, using reflection to implement function callback handlers []handler///store handles all middleware actions for HTTP request Handler//route matching and routing processing, after all middleware has finished processing logger *lo G.logger//Log tool}//Base skeleton: Basic injection and reflection call Function//New creates a bare bones Martini instance. Use this method if you want to has full control over the middleware, is Used.func New () *martini {m: = &martini{i Njector:inject. New (), Action:func () {}, Logger:log. New (OS. Stdout, "[Martini]", 0)}m.map (m.logger) M.map (Defaultreturnhandler ()) return m}//handlers sets the entire middleware Stack with the given handlers. This would clear any current middleware handlers.//would panic if any of the handlers are not a callable function//set all middleware Func (M *martini) handlers (handlers ... Handler) {m.handlers = make ([]handler, 0) for _, Handler: = Range Handlers {M.use (handler)}}//Action sets the handler that'll be called after all the middleware have been invoked. This is the set to Martini. Router in a martini. Classic ().//Set up a real routing processor and execute func (M *martini) Action (handler handler) {Validatehandler (handler) M.action = When all middleware finishes executing handler}//Logger Sets the Loggerfunc (M *martini) Logger (Logger *log. Logger) {M.logger = Loggerm. Map (M.logger)}//use adds a middleware Handler to the stack. Would panic if the handler is not a callable func. Middleware handlers is invoked in the order that they is added.//to add a middleware processor, each HTTP request is executed first, followed by Func in the order added (M *martini ) Use (handler handler) {Validatehandler (handler) m.handlers = Append (m.handlers, handler)}//HTTP interface, ingress per HTTP request User level Processing Servehttp is the HTTP Entry point for a Martini instance. Useful if you want to control your own HTTP Server.func (M *martini) servehttp (res http. Responsewriter, req *http. Request) {println ("call ...") M.createcontext (res, req). Run ()//each request creates a context, saves some necessary information, and then starts processing the request}//RUN the HTTP server on a given host and port.//HTTP Server start func (M *martini) runonaddr (addr string) {//Todo:should PROBABL Y be implemented using a new instance of HTTP. Server in place of//calling HTTP. Listenandserver directly, so that it could is stored in the Martini struct for later use.//this would also allow to Impro ve testing when a custom host and port is Passed.logger: = M.injector.get (reflect. TypeOf (M.logger)). Interface (). (*log. Logger) Logger. Printf ("Listening on%s (%s) \ n", addr, Env) logger. Fatalln (http. Listenandserve (addr, m))//M is the beginning of the entire framework control}//Run the HTTP server. Listening on OS. GETENV ("port") or Default.func (M *martini) Run () {port: = OS. Getenv ("port") If Len (port) = = 0 {port = "}host": = OS. Getenv ("host") M.runonaddr (Host + ":" + port)}//creates the request context, as is the case with most web frameworks, and uses context to store related data in the process of processing the request func (M *martini) Createcontext (res http. Responsewriter, req *http. Request) *context {///Newresponsewriter The Res and added some additional features, such as a filter such as c: = &context{inject. New (), M.handlers, M. Action, Newresponsewriter (RES), 0}c.setparent (m) C.mapto (c, (*context) (nil))//context is an interface type, C is a concrete type struct that implements the Context interface This is to do an interface and implementation of the mapping, using the implementation can only use the mapping type has been implemented interface C. Mapto (C.RW, *http. Responsewriter) (nil))//RW is also mapped to interface{} type C. MAP (req)//req is a specific type, here just want to store this value return c}//classic collocation, integrated routing and Martini core function//Classicmartini represents a Martini with some Rea sonable defaults. Embeds the router functions for Convenience.type classicmartini struct {*martini//router//Anonymous variable type requires an object that implements all interfaces, so the CLA Ssicmartini instances can call router interfaces seamlessly, such as M. Get (pattern, handler)}//Classic creates a classic Martini with some basic default Middleware-martini. Logger, Martini. Recovery and Martini. static.//Classic also maps martini. Routes as a service.func Classic () *classicmartini {r: = Newrouter ()//base router for storing user-defined routing rules and processor m: = New ()//martini base frame M . Use (Logger ())//Add log processing middleware M. Use (Recovery ())//server exception error when processing M. Use (Static ("public"))//Static file processing M.mapto (R, (*routes) (nil))//nil means only one type M is required. Action (R.handle)//All router middleware executed only after executionProcessing, equivalent to formal route matching processing, middleware to do some web routine necessary processing return &classicmartini{m, r}}//Handler can be any callable function. Martini attempts to inject services into the handler ' s argument list.//Martini would panic if an argument could not being ful Lfilled via Dependency injection.//defines the Handler type as a generic type Handler interface{}//checks if Handler is a function type Func validatehandler ( Handler handler) {if reflect. TypeOf (handler). Kind ()! = reflect. Func {Panic ("Martini handler must be a callable func")}}//Context represents a request Context. Services can be mapped on the Interface.type context interface {//contains all interfaces of another interface type, and the instance of the context must implement the There is an interface, or contains an anonymous concrete case to implement all of the interface inject. Injector//middleware is executed sequentially during sequential execution, using the next interface constantly updating the index to point to the next middleware next ()//written returns whether or not the response for this Contex T has been written.//returns whether the HTTP request has been processed and sent an answer to the identity written () bool}//The context instance of the HTTP request processing of the type contextual struct {//contains an interface type, initialization requires a Examples of concrete implementations, a case of dependency injection, injection of specific functions, and the runtime callback each function inject in order. Injector//handler array, which processes an HTTP request in order one by one execution handlers []hAndler//is actually the last handleraction Handler//on HTTP. Responsewriter further encapsulation, adding more features, such as filters, before after processing RW Responsewriter//Indicates the index of the current nth hanlder indexed by x int}//take out the current nth processor, as If the index value reaches the maximum value, the action function is returned, which is the start route matching logical func (c *context) handler () handler {if C.index < Len (c.handlers) {return c.handlers[c . index]}if C.index = = Len (c.handlers) {return c.action}panic ("Invalid index for context handler")}//update points to the next processor, After continuing the processing of the remaining processor to the request Func (c *context) Next () {C.index + = 1c.run ()}//Determine whether the answer has been sent, if it has been sent, then do not need to process Func (c *context) written () Boo L {return C.rw.written ()}//gets the current processor and processes the HTTP request, executes a series of processing func (c *context) run () {for c.index <= len (c.handlers) {_, Err : = C.invoke (C.handler ())//Invoke callback on arrest, return structure stored in contextif err! = Nil {panic (err)}c.index + = 1//For loop first performs call processing and then updates the index, so with Next update index does not conflict if C.written () {return}}}

  If there are errors in understanding, welcome in the comments pointed out, greatly appreciated!

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.