需要的知识点

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

  • 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. java中checked和unchecked 异常处理

    有两种类型的异常:一种是checked异常一种是unchecked异常,在这篇文章中我们将利用实例来学习这两种异常,checked的异常和unchecked异常最大的区别就是checked去唱是在编译 ...

  2. CAP理论(摘)

    先解释一下软件编程中常见的一些概念: 抽象先于具象.这个抽象并非虚无的抽象,而是指事物尚未分化为具象之前的那个前体存在.当那个前体存在分化成具象存在之后,前体存在就退化为背景,成为一种抽象. 结构是关 ...

  3. 50. Pow(x, n) (INT; Divide-and-Conquer)

    Implement pow(x, n). 思路:二分法,将每次相乘,转化成平方. class Solution { public: double myPow(double x, int n) { ) ...

  4. jsoncpp在Windows和Linux下的安装

    Windows下: 参考这个网站,没什么问题,注意MTd这些选对就行了. http://www.cppblog.com/wanghaiguang/archive/2013/12/26/205020.h ...

  5. python的paramiko模块简单应用

    用法1,SSHClient 分别可以使用密码和秘钥登陆,然后执行命令,并且获取执行结果 import paramiko #创建一个SSH对象 ssh = paramiko.SSHClient() #允 ...

  6. python之文件操作read

    #open函数,该函数用于文件处理,文件操作一共就有三种方法,打开文件#关闭文件, #先来说下打开文件,打开文件的模式有下面几种# 1.r,只读模式 f = open('test.log','r',e ...

  7. 乱序字符串anagrams

    [抄题]: 给出一个字符串数组S,找到其中所有的乱序字符串(Anagram).如果一个字符串是乱序字符串,那么他存在一个字母集合相同,但顺序不同的字符串也在S中. 对于字符串数组 ["lin ...

  8. ViewPager 带动画的欢迎界面

    一般APP进去之后都会有几张图片来导航,这里就学习怎么在这张图片切换的时候添加切换动画效果 先看布局文件 activity_main.layout <?xml version="1.0 ...

  9. 帧动画 连续播放多张图片动画 以及ui动画 SoundPool

    drawable下有很多图片  可以 <?xml version="1.0" encoding="utf-8"?> <animation-li ...

  10. IDEA 工具下导出文件及文件的目录结构插件

    idea导出增量补丁插件 有时候需要导出IDEA的文件目录结构,即导出  指定修改后的JAVA文件编译后的CLASS .或者是修改过的jsp.配置文件等, 装载此插件,即可以完成导出文件  及文件的目 ...