This is a creation in Article, where the information may have evolved or changed. # Bingo This is a thing I've been writing lately ... Just transferred from PHP, the features of Go is not very understanding, apply a bit gin, think although very good, but some grammar is not laravel so convenient so want to recreate a wheel to see ... en ... The sauce bingo is a lightweight API framework based on the go language, focused on building Restfulapigithub address: [Silsuer/bingo] (Https://github.com/silsuer/bingo) Recently I made a lot of changes, Gayhub on the article is very inconsistent with this, so here again to paste the commit link out [point here ~] (https://github.com/silsuer/bingo/commit/ 51504CE73687C73596E3DF260724A6203241BBFE) # # Directory structure-app placement and site-related code-core placement Framework core code A-vendor placing third-party libraries, using glide to manage third-party libraries-public HTML code # # # development process Go's net package is extremely easy to use, it is extremely fast to develop frameworks (incredibly faster than writing PHP frameworks ...). First determine the main function, instantiate a struct in the main function, and then call the run function in it to do it: "Go func main () {//New Bingo object, then bingo. Run () to//specify static directory, default point to index.html, load route file//Load env file Bingo: = new (core. Bingo) Bingo. Run (": 12345")} "next go to write Bingo file: ' Go func (b *bingo) Run (port string) {//pass in a port number, no return value, turn on HTTP listener based on port number//Here to initialize resources, load All routes, profiles, and so on//instantiate the Router class, this class goes to get all the JSON files in the router directory, and then, based on the configuration in JSON, loads the data//instanced env file and all the data under the Config folder, according to the configuration//according to the routing list, Start defining the route and, depending on the port number, turn on HTTP server http. Listenandserve (port, Bin)//TODO listener smooth upgrade and restart} ' Run ' function non-Often simple, only one line of code, is to open an HTTP server and listen to the incoming port, because we have to control all kinds of routes, so we can not use the net package of the HTTP service, there are many principles on the Internet is very clear that we need to implement the ' servehttp ' method, To implement the MUX of this router interface, so write a ' servehttp ' method ' Go func (b *bingo) servehttp (w http. Responsewriter, R *http. Request) {flag: = FALSE//This variable is used to mark whether dynamic routing is found//each HTTP request will come here, and here, according to the requested URL, assign it the method that needs to be called params: = []reflect. Value{reflect. ValueOf (w), reflect. ValueOf (R)} for _, V: = range Routeslist {//detection middleware, according to middleware first open middleware, and then register other routes//detect routes, according to the route to the required data if R.url. Path = = V.path && R.method = = V.method {flag = TRUE//Find the corresponding route, do not need to use static server//todo call a common middleware, in this middleware to find routes and call middleware finishing can//detect if there is middleware in this route, if present, call for _, M: = Range V.middleware {if mid, OK: = Middlewaremap[m]; OK {//determine if this middleware Rmid is registered): Reflect. ValueOf (mid) params = Rmid. Methodbyname ("Handle"). Call (params)//execute middleware, return values array//judge the results of the middleware execution, whether or not to continue to go down str: = Rmid. Elem (). Fieldbyname ("resstring"). String () if str! = "" {Status: = Rmid. Elem (). Fieldbyname ("Status"). Int ()//String not empty, view status code, default return 500 error if status = = 0 {status = $} w.writeheader (int (status)) Fmt. Fprint (W,STR) Return}}}//Detect success, start calling method//Get structure under a controller package if d, OK: = Controllermap[v.controller]; OK {//existence C is struct, call C on Mount method reflect. ValueOf (d). Methodbyname (v.function). Call (params)}//Stop Backwards Execution return}}//If the routing list is still not there, go to the static server and look for the IF!flag {//go to the static directory for HTTP. Servefile (W,r,getpublicpath () + R.url. Path)} ' return} ' can be seen, we use the Servehttp method redefined, in this method, we based on the browser access to different URLs, by reflection to get different controller or middleware structure, and call the corresponding method, If the URL of the access we do not define, will go to the static folder to look for, if found, output static files, otherwise output 404 page (p.s.) because we are going to implement a stateless API rapid development framework, so no template rendering is required, all data is transferred to the page via Ajax Note that in this function I use ' middlewaremap[m ' and ' controllermap[m ', which is a map of the middleware and the controller, which will be stored in memory when the program is initialized specifically as follows: ' ' Go// This records all the structures that should be registered//controller map var Controllermap map[string]interface{}//middleware map var middlewaremap map[string]interface{} Fun C init () {Controllermap = make (map[string]interface{}) Middlewaremap = Make (map[string]interface{})//Assign initial values to these two maps each time you finish adding A route or middleware where the routing or middleware is registered here//registered middleware middlewaremap["Webmiddleware"] =&middleware. webmiddleware{}//Register routing controllermap["ContRoller "] = &controller. controller{}} "Here we use the structure of the App/controller and the middleware package, and when the route parsing is complete, the path of the request is mapped to the map here, and now we look at the parsing route code in router:" Gotype route struct {path string//path target string//corresponding controller path Controller@index such method string//access type is get post or other Alias string//route aliases Middleware []string//Middleware Name Controller string//Controller name function string//Mount method name on controller}type Route_grou P struct {Root_path string//Path Root_target string//corresponding controller path Controller@index such method alias string//route aliases Middleware []STR ing//middleware name Routes []route///included Routes}var Routes []route//Single route collection var routesgroups []route_group//Routing group collection Var routeslist []r Oute//All routes list var R interface{}func init () {//Initialize method, load route file//Get route path, get all route files based on routing path, then read all files, assign to current member variable Routes_path: = Getroutespath () dir_list, err: = Ioutil. ReadDir (Routes_path) Check (ERR)///According to Dir list traverse all files to get all JSON files, get all routing routing group for _, V: = Range Dir_list {fmt. PRINTLN ("Loading routing files ..." + v.name ())//Read file contents, convert to JSON, and add content in array, err: = filegetcontents (Routes_path + "/" + V. Name ()) Check (err) Err = json. Unmarshal ([]byte (content), &r) Check (ERR)//Start parsing R, classify it into global variables parse (r)}} "" Executes the init function at the stage of preparing the compilation and obtains all the routing lists under the Routing folder , we use JSON format to organize the route, parse out the data into the Routeslist list below is the parse code ' Gofunc parse (r interface{}) {//Get R we want to parse into actual data m: = R. (Map[string] interface{})//newroute: = Route{}for k, V: = range m {if k = = "Routes" {//Parse single route parseroutes (v)}if k = = "Routesgroups" {// Resolve Routing Group parseroutesgroups (v)}}}//parse the collection of single routes in the JSON file Func parseroutes (r interface{}) {m: = R. ([]interface{}) for _, V: = Range m {//V is a single routed simpleroute: = V. (map[string]interface{})//Define a routing structure newroute: = Route{}for KK, vv: = Range Simpleroute { Switch KK {case "Route": Newroute.path = vv. (string) breakcase "Target": Newroute.target = vv. (string) breakcase "Method": Newroute.method = vv. (string) breakcase "Alias": Newroute.alias = vv. (string) breakcase "middleware":// Newroute.middleware = vv. ([]) var mdw []STRINGVVM: = vv. ([]interface{}) for _, VVV: = Range VVM {mdw = append (MDW, VVV. string))}newroute.middleware = Mdwbreakdefault:break}}//to split target into the controller and method CF: = Strings. Split (Newroute.target, "@") if Len (cf) ==2 {newroute.controller = Cf[0]newroute.function = cf[1]}else{fmt. PRINTLN ("Target format is wrong! +newroute.target) return}//This new route to a single route slice, and also to the routing list Routes = append (Routes, newroute) routeslist = append ( Routeslist, Newroute)}}func parseroutesgroups (r interface{}) {//Resolution routing Group M: = R. ([]interface{}) for _, V: = range m {Group: = V. (map[string]interface{}) for KK, VV: = Range Group {//New routing group structure var newgroup route_groupswitch kk {case "Rootroute": NEWG Roup.root_path = vv. (string) breakcase "Roottarget": Newgroup.root_target = vv. (string) breakcase "middleware": Var mdw [] STRINGVVM: = vv. ([]interface{}) for _, VVV: = Range VVM {mdw = append (MDW, VVV. ( string))}newgroup.middleware = Mdwbreakcase "Routes"://due to concepts such as root routing, it is not possible to use the Parseroutes method above, you need to write a method to parse the real route RS: Parserootroute (group) newgroup.routes = rsbreakdefault:break}//put the group in the routing group routesgroups = append (routesgroups, newgroup)}}}//resolves the root route to the root routing path target followed by the path and the incoming route Inteface list, returning aComplete routing set//Only one routing group, return a complete set of routes func Parserootroute (group map[string]interface{}) []route {//Get route root path and target root path, and public middleware Var tmproutes []route//To return the route slice var route_root_path stringvar target_root_path stringvar public_middleware []stringfor K, V: = Range Group {if k = = "Rootroute" {Route_root_path = V. (string)}if k = = "Roottarget" {Target_root_path = V. (string)}if k= = "Middleware" {vvm: = V. ([]interface{}) for _, VVV: = Range VVM {public_middleware = append (Public_middleware, VVV. String)}}}//begins to get the route for K, s: = Range Group {if k = = "Routes" {m: = S. ([]interface{}) for _, V: = range m {//V is a single routed sim Pleroute: = V. (map[string]interface{})//Define a routing structure body newroute: = route{}for KK, vv: = range simpleroute {switch KK {case "Rou TE ": Newroute.path = route_root_path+ vv. (string) breakcase" Target ": Newroute.target = target_root_path+ vv. (string) Breakcase "Method": Newroute.method = vv. (string) breakcase "Alias": Newroute.alias = vv. (string) breakcase "middleware": VVM: = vv. ([]interface{}) for _, VVV: = Range VVM{newroute.middleware = append (public_middleware,vvv. ( String)//public and newly joined together is the total}breakdefault:break}}//to split target into controller and method CF: = Strings. Split (Newroute.target, "@") if Len (cf) ==2 {newroute.controller = Cf[0]newroute.function = cf[1]}else{fmt. PRINTLN ("Target format is wrong! "+newroute.target) os. Exit (2)}//This new route to the routing list and returns it to the route collection, returning routeslist = Append (routeslist, newroute) tmproutes = append (Tmproutes, Newroute}}}} "return tmproutes}" to get a list of routes by parsing the JSON file, and then compare the routing list in the Servehttp file above. In this context, we implemented a simple web framework that uses go to present only static pages and API responses the next thing we want to achieve is: 1. A handy ORM 2. Create a quick Add controller and Middleware command 3. Implement database Migration 4. Implement token-based API Authentication 5. Data Cache 6. Queue 7. Hook 8. Convenient file upload/storage function for Star, welcome pr~ hahaha ([Silsuer/bingo] (Https://github.com/silsuer/bingo)) 1623 reads
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