需要的知识点

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

  • 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. scala -- 柯里化

    柯里化 柯里化是把接受多个参数的函数,变成接受一个单一参数的函数.并且返回接受剩余参数和返回结果的新函数. 就是一个逐次消元的过程. 当把函数的元全消掉,就得到了值. 值就是零元函数. 二元函数 f( ...

  2. 判断一个对象是否为真 __nonzero__ 方法和 __len__方法

    class A(): def __nonzero__(self): # 判断 一个对象是否为空,先查看该方法的返回值 return 1 def __len__(self): # 如果没有上一个方法,那 ...

  3. How to create a Virtual Machine in SmartOS

    在SmartOS中,使用vmadm创建工具创建虚拟机. 此工具需要一个JSON有效负载,并使用输入JSON中指定的属性创建“kvm”或“joyent” brand zone. 正常输出是一系列单行JS ...

  4. 运行Maven项目时出现invalid LOC header (bad signature)

    为Maven小白,今天这问题困扰了我好久,经过多次在网上查询,终于找到了原因.明明一个小问题却耗费很多时间,着实不应该,所以必须记录一下. 报错信息如下:   对话框: 控制台: <span s ...

  5. 部分2020年交期的PR回写到SAP中

    描述:此问题一直存在,只是用户没有发现,最近提出,部分2020年交期的PR回写到SAP中 优化: SELECT MAX (PR.ORDERID), PR.ITEM, SUBSTR (PR.RECOMM ...

  6. richface的配置、用法介绍和注意事项

    richface的配置.用法介绍和注意事项一.RichFaces (3.1.x) 技术需求 1.JDK 1.5 或更高版本: 2.支持的 JSF 实现: Sun JSF 1.1 RI - 1.2 My ...

  7. Dungeon Game (GRAPH - DP)

    QUESTION The demons had captured the princess (P) and imprisoned her in the bottom-right corner of a ...

  8. clamp 函数

    返回范围内的一个数值.可以使用 clamp 函数将不断增加.减小或随机变化的数值限制在一系列的值中. float clamp(float minnumber, float maxnumber, flo ...

  9. 【校招面试 之 剑指offer】第18题 删除链表中的节点

    题目一:在O(1)时间内删除链表节点. 给定单项链表的头指针和一个节点指针,定义一个函数在O(1)时间内删除该节点. 思路:(1)如果要删除的节点不是链表的尾节点,则将被删除节点的内容复制到该节点,然 ...

  10. 安全运维 -- 更改ssh端口

    环境:Ubuntu 16 前言 黑客遍地都是,ssh/pop3/ftp等爆破工具的流行让站长的日常运维工作量大大加重.Metasplot,Bruter等工具更是针对以上协议有专门 的破解方法,有字典破 ...