zoukankan      html  css  js  c++  java
  • GO语言之web服务

    前言:go语言搭建文本服务很简单,几行代码就可以搭建一个稳定 高并发的web server

    为什么相较于其他的语言GO的优势在哪里呢?我们带着问题往下看

    一个go web服务器正常运行起来大概需要以下几个步骤: 
        - 创建listen socket,循环监听listen socke 
        - accept接受新的链接请求,并创建网络连接conn,然后开启一个goroutine负责处理该链接。 
        - 从该链接读取请求参数构造出http.Request对象,然后根据请求路径在路由表中查找,找到对应的上层应用的处理函数,把请求交给应用处理函数。 
        - 应用处理函数根据请求的参数等信息做处理,返回不同的信息给用户 
        - 应用层处理完该链接请求后关闭该链接(正常流程,如果是http alive则不关闭该链接)

    这里面路由表是比较重要的,我们具体分析下http.Server是如何做路由的。 
        路由表实际上是一个map 
        key是路径 ==> “/hello” 
        value是该路径所对应的处理函数 ==> HelloServer

    // hello world, the web server
    func HelloServer(w http.ResponseWriter, req *http.Request) {
        io.WriteString(w, "hello, world!
    ")
    }
    func main() {
        http.HandleFunc("/hello/", HelloServer)
        err := http.ListenAndServe(":8080", nil)
        if err != nil {
            log.Fatal("ListenAndServe: ", err)
        }
    }
    

      

     路由表结构

     go语言默认的路由表是 ServeMux,结构如下

    type ServeMux struct {
        mu    sync.RWMutex
        m     map[string]muxEntry //存放具体的路由信息 
    }
    type muxEntry struct {
        explicit bool
        h        Handler
        pattern  string
    }
    //muxEntry.Handler是一个接口
    type Handler interface {
        ServeHTTP(ResponseWriter, *Request)
    }
    //这边可能会有疑惑 
    //http.HandleFunc("/hello/", HelloServer)
    //helloServer是一个function啊,并没有实现ServeHTTP接口啊
    //这是因为虽然我们传入的是一个function,但是HandleFunc会把function转为实现了ServeHTTP接口的一个新类型 HandlerFunc。
    /*
    func (mux *ServeMux) HandleFunc(pattern string, handler     func(ResponseWriter, *Request)) {
        mux.Handle(pattern, HandlerFunc(handler))
    }
    type HandlerFunc func(ResponseWriter, *Request)
    // ServeHTTP calls f(w, r).
    func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
        f(w, r)
    }
    */
    

      

     路由注册过程

    注册过程其实就是往map中插入数据,值得注意的一个地方是如果 
    注册路径是/tree/并且没有/tree的路由信息,那么会在路由表中自动增加一条/tree的路由,

    /tree的处理函数是重定向到/tree/。但是如果注册的是/tree是不会自动添加/tree/的路由的

    // Handle registers the handler for the given pattern.
    // If a handler already exists for pattern, Handle panics.
    func (mux *ServeMux) Handle(pattern string, handler Handler) {
        mux.mu.Lock()
        defer mux.mu.Unlock()
        mux.m[pattern] = muxEntry{explicit: true, h: handler, pattern: pattern}
        n := len(pattern)
        if n > 0 && pattern[n-1] == '/' && !mux.m[pattern[0:n-1]].explicit {
            path := pattern
            fmt.Printf("redirect for :%s to :%s", pattern, path)
            mux.m[pattern[0:n-1]] = muxEntry{h: RedirectHandler(path, StatusMovedPermanently), pattern: pattern}
        }
    }
    

      

    路由查找过程

    路由查找过程就是遍历遍历路由表,找到最长匹配请求路径的路由信息并返回,如果找不到返回 NotFoundHandler

    func (mux *ServeMux) handler(host, path string) (h Handler, pattern string) {
        mux.mu.RLock()
        defer mux.mu.RUnlock()
        if h == nil {
            h, pattern = mux.match(path)
        }
        if h == nil {
            h, pattern = NotFoundHandler(), ""
        }
        return
    }
    func (mux *ServeMux) match(path string) (h Handler, pattern string) {
        var n = 0
        for k, v := range mux.m {
            if !pathMatch(k, path) {
                continue
            }
            //找出匹配度最长的
            if h == nil || len(k) > n {
                n = len(k)
                h = v.h
                pattern = v.pattern
            }
        }
        return
    }
    // 如果路由表中的路径是不以下划线结尾的 /hello
    //那么只有请求路径为/hello 完全匹配时才符合
    //如果路由表中的注册路径是以下划线结尾的 /hello/
    //那么请求路径只要满足/hello/* 就符合该路由
    func pathMatch(pattern, path string) bool {
        n := len(pattern)
        if pattern[n-1] != '/' {
            return pattern == path
        }
        return len(path) >= n && path[0:n] == pattern
    }
    

      

  • 相关阅读:
    指针系统学习5-对使用字符指针变量和字符数组的讨论
    指针系统学习4-字符串与指针
    指针系统学习3-多维数组与指针
    指针系统学习2
    指针系统学习1
    你视为意见领袖的大 V,可能只是个僵尸号
    phpinfo()
    用shell脚本守护后台进程
    mysql命令(command)
    MySQL数据库视图(view),视图定义、创建视图、修改视图
  • 原文地址:https://www.cnblogs.com/laogao123/p/11009607.html
Copyright © 2011-2022 走看看