需要的知识点

为了防止你的心里不适,需要以下知识点:

  • Go 基本知识
  • Go 反射的深入理解
  • 使用过框架

Go Web 服务器搭建

package main

import (
"fmt"
"net/http"
) func do(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello World!") //这个写入到w的是输出到客户端的
} func main() {
http.HandleFunc("/", do) //设置访问的路由
http.ListenAndServe(":9090", nil) //设置监听的端口
}

上面的例子调用了http默认的DefaultServeMux来添加路由,需要提供两个参数,第一个参数是希望用户访问此资源的URL路径(保存在r.URL.Path),第二参数是即将要执行的函数,以提供用户访问的资源。

Go默认的路由添加是通过函数http.Handlehttp.HandleFunc等来添加,底层都是调用了DefaultServeMux.Handle(pattern string, handler Handler),这个函数会把路由信息存储在一个map信息中map[string]muxEntry。

Go监听端口,然后接收到tcp连接会扔给Handler来处理,上面的例子默认nil即为http.DefaultServeMux,通过DefaultServeMux.ServeHTTP函数来进行调度,遍历之前存储的map路由信息,和用户访问的URL进行匹配,以查询对应注册的处理函数。

你可以通过文档查看 http.ListenAndServe 的方法,第二个参数是 Handler 类型的接口,只要实现 Handler 接口,就可以实现自定义路由。

func ListenAndServe(addr string, handler Handler) error

实现自定义路由:

package main

import (
"fmt"
"net/http"
) type MyMux struct {
} func (p *MyMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/" {
sayhelloName(w, r)
return
}
http.NotFound(w, r)
return
} func sayhelloName(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello myroute!")
} func main() {
mux := &MyMux{}
http.ListenAndServe(":9090", mux)
}

通过自定义路由,实现简单 MVC 框架

两个基本结构的定义:

type controllerInfo struct {
url string
controllerType reflect.Type
} type ControllerRegistor struct {
routers []*controllerInfo
}

整体思路:

  • controllerInfo url 是添加时候对应的路由, controllerType 反射类型。
  • 通过 mux.Add("/", &DefaultController{}) 前台添加的信息,放到一个 routers []*controllerInfo 数组中
  • 每一次请求都会遍历 routes, 判断当前的   r.URL.Path 是否与 routes 里面一个相等,如果相等, 通过类型反射,执行相应的方法。

流程图:

源码实现

package main

import (
"fmt"
"net/http"
"reflect"
) type controllerInfo struct {
url string
controllerType reflect.Type
} type ControllerRegistor struct {
routers []*controllerInfo
} type ControllerInterface interface {
Do()
} type UserController struct { } type DefaultController struct { } func (u *UserController) Do() {
fmt.Println("I`m UserController")
} func (d *DefaultController) Do() {
fmt.Println("I`m DefaultController")
} func (p *ControllerRegistor) Add(pattern string, c ControllerInterface) { //now create the Route
t := reflect.TypeOf(c).Elem()
route := &controllerInfo{}
route.url = pattern
route.controllerType = t
p.routers = append(p.routers, route) } // AutoRoute
func (p *ControllerRegistor) ServeHTTP(w http.ResponseWriter, r *http.Request) { var started bool
requestPath := r.URL.Path fmt.Println(requestPath) //find a matching Route
for _, route := range p.routers { if requestPath == route.url {
vc := reflect.New(route.controllerType)
method := vc.MethodByName("Do")
method.Call(nil)
started = true
fmt.Fprintf(w, "Hello " + route.controllerType.Name())
break
}
} //if no matches to url, throw a not found exception
if started == false {
http.NotFound(w, r)
}
} func main() {
mux := &ControllerRegistor{} mux.Add("/", &DefaultController{})
mux.Add("/user", &UserController{}) s := &http.Server{
Addr: ":9527",
Handler: mux,
} s.ListenAndServe()
}

以上只是一个简陋的实现思路,可以优化加上具体的功能和通过参数调用方法等。

 参考链接:

Go Web 编程

一个简单 Go Web MVC 框架实现思路的更多相关文章

  1. Node.js简单介绍并实现一个简单的Web MVC框架

    编号:1018时间:2016年6月13日16:06:41功能:Node.js简单介绍并实现一个简单的Web MVC框架URL :https://cnodejs.org/topic/4f16442cca ...

  2. 用Python写一个简单的Web框架

    一.概述 二.从demo_app开始 三.WSGI中的application 四.区分URL 五.重构 1.正则匹配URL 2.DRY 3.抽象出框架 六.参考 一.概述 在Python中,WSGI( ...

  3. 一个简单的web框架实现

    一个简单的web框架实现 #!/usr/bin/env python # -- coding: utf-8 -- __author__ = 'EchoRep' from wsgiref.simple_ ...

  4. 动手写一个简单的Web框架(模板渲染)

    动手写一个简单的Web框架(模板渲染) 在百度上搜索jinja2,显示的大部分内容都是jinja2的渲染语法,这个不是Web框架需要做的事,最终,居然在Werkzeug的官方文档里找到模板渲染的代码. ...

  5. 动手写一个简单的Web框架(Werkzeug路由问题)

    动手写一个简单的Web框架(Werkzeug路由问题) 继承上一篇博客,实现了HelloWorld,但是这并不是一个Web框架,只是自己手写的一个程序,别人是无法通过自己定义路由和返回文本,来使用的, ...

  6. 动手写一个简单的Web框架(HelloWorld的实现)

    动手写一个简单的Web框架(HelloWorld的实现) 关于python的wsgi问题可以看这篇博客 我就不具体阐述了,简单来说,wsgi标准需要我们提供一个可以被调用的python程序,可以实函数 ...

  7. CodeIgniter框架——创建一个简单的Web站点(include MySQL基本操作)

    目标 使用 CodeIgniter 创建一个简单的 Web 站点.该站点将有一个主页,显示一些宣传文本和一个表单,该表单将发布到数据库表中. 按照 CodeIgniter 的术语,可将这些需求转换为以 ...

  8. Spring 4 官方文档学习(十一)Web MVC 框架之配置Spring MVC

    内容列表: 启用MVC Java config 或 MVC XML namespace 修改已提供的配置 类型转换和格式化 校验 拦截器 内容协商 View Controllers View Reso ...

  9. struts1:(Struts重构)构建一个简单的基于MVC模式的JavaWeb

    在构建一个简单的基于MVC模式的JavaWeb 中,我们使用了JSP+Servlet+JavaBean构建了一个基于MVC模式的简单登录系统,但在其小结中已经指出,这种模式下的Controller 和 ...

随机推荐

  1. Windows10系统一键结束所有运行程序

    当电脑及其卡顿的时候,想打开任务管理器关掉所有运行的程序的时候,也会变得及其困难.因此之前你如果有犀利的小程序设置,这都不会是问题. 1)空白处右键-新建-快捷方式 2)将下列代码复制到下列框中(注意 ...

  2. DESeq2包

    1)简介: DESeq2-package: for differential analysis of count data(对count data 做差异分析) 2)安装 if("DESeq ...

  3. kegg富集分析之:KEGGREST包(9大功能)

    这个包依赖极有可能是这个:https://www.kegg.jp/kegg/docs/keggapi.html ,如果可以看懂会很好理解 由于KEGG数据库分享数据的策略改变,因此KEGG.db包不在 ...

  4. What is API Level?

    [What is API Level?] 参考:http://android.xsoftlab.net/guide/topics/manifest/uses-sdk-element.html#ApiL ...

  5. Python locals() 函数

    Python locals() 函数  Python 内置函数 描述 locals() 函数会以字典类型返回当前位置的全部局部变量. 对于函数, 方法, lambda 函式, 类, 以及实现了 __c ...

  6. 硬盘的 read0 read 1

    Read 0:组建的时候必须2块容量相同的硬盘,每个程序的数据以一定的大小分别写在两个硬盘里,读的时候从两个硬盘里一起读,这种阵列方式理论上硬盘的读写速度是一块硬盘的2倍,实际应用中大约速度比一块硬盘 ...

  7. xcode10 出现 框架 或者 pod 出错

    1. 报错 Showing Recent Messages :-1: Multiple commands produce '/Users/apple/Library/Developer/Xcode/D ...

  8. sql ltrim/rtrim 字段中为中文时出现?的问题

    字段存储为中文,类型为nvarchar,使用ltrim时结果集中出现的问号,我的解决办法是:将问号replace掉

  9. linq to sql之like

    contains——like '%提交%' StartsWith—— like '条件%' EndWith——like '%条件'

  10. loadrunner11--集合点(Rendezvous )菜单是灰色不能点击

    新建场景的时候“Manual Scenario”下的check box不能选中,取消选中就好了.即Vuser不能以百分比的形式. 所以:集合点灰化有两种情况: 脚本没有添加集合点函数 场景中设置以Vu ...