1、网络基础

基本TCP客户-服务器程序Socket编程流程如如下图所示。

TCP服务器绑定到特定端口并阻塞监听客户端端连接,

TCP客户端则通过IP+端口向服务器发起请求,客户-服务器建立连接之后就能开始进行数据传输。

Golang的TCP编程也是基于上述流程的。

2、Golang HTTP编程

2.1 代码示例

func timeHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "%v", time.Now().Format(time.RFC3339))
} func helloHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "%v", "hello world.")
} func main() {
// 1. 新建路由解码器
h := http.NewServeMux()
// 2. 路由注册
h.HandleFunc("/hello", helloHandler)
h.HandleFunc("/time", timeHandler)
// 3. 服务启动 阻塞监听
http.ListenAndServe(":8000", h)
}

运行上述程序,在浏览器地址栏分别输入 http://localhost:8000/hello http://localhost:8000/time 结果分别如下图所示。

 

2.2 源码分析

分析从路由注册到响应用户请求的流程。

2.2.1 新建解码器 h := http.NewServeMux()

type ServeMux struct {
mu sync.RWMutex
m map[string]muxEntry
es []muxEntry // slice of entries sorted from longest to shortest.
hosts bool // whether any patterns contain hostnames
}
type muxEntry struct {
h Handler
pattern string
}
// NewServeMux allocates and returns a new ServeMux.
func NewServeMux() *ServeMux { return new(ServeMux) }

Handler是interface,定义如下

type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}

ServeMux实现了Handler接口。

2.2.2 路由注册 h.HandleFunc("/hello", helloHandler)

// HandleFunc registers the handler function for the given pattern.
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
...
mux.Handle(pattern, HandlerFunc(handler))
} func (mux *ServeMux) Handle(pattern string, handler Handler) {
...
e := muxEntry{h: handler, pattern: pattern}
mux.m[pattern] = e
if pattern[len(pattern)-1] == '/' {
mux.es = appendSorted(mux.es, e)
}
...
}

timeHandlerhelloHandler函数被强制转换为type HandlerFunc func(ResponseWriter, *Request)类型,且实现了Handler接口。

func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}

mux.m建立了路由到处理函数timeHandlerhelloHandler的映射。

2.2.3 服务启动阻塞监听 http.ListenAndServe(":8000", h)

包装Server结构体,HTTP使用TCP协议。

func ListenAndServe(addr string, handler Handler) error {
server := &Server{Addr: addr, Handler: handler}
return server.ListenAndServe()
}
func (srv *Server) ListenAndServe() error {
...
ln, err := net.Listen("tcp", addr)
if err != nil {
return err
}
return srv.Serve(ln)
}

net.Listen封装了Socket编程的socketbindlisten的调用,极大的方便了使用者。

阻塞监听请求,新建goroutine处理每个新请求。

func (srv *Server) Serve(l net.Listener) error {
...
for {
rw, err := l.Accept()
...
c := srv.newConn(rw)
c.setState(c.rwc, StateNew, runHooks) // before Serve can return
go c.serve(connCtx)
}
}
// Serve a new connection.
func (c *conn) serve(ctx context.Context) {
...
serverHandler{c.server}.ServeHTTP(w, w.req)
...
}
func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) {
handler := sh.srv.Handler
...
handler.ServeHTTP(rw, req)
}

通过前面的流程推导可知,handler是http.ListenAndServe的第二个参数ServeMux

// ServeHTTP dispatches the request to the handler whose
// pattern most closely matches the request URL.
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
...
h, _ := mux.Handler(r) // 通过路由获取处理函数
h.ServeHTTP(w, r)
}

mux.Handler使用mux.m这个map通过请求URL找到对应处理函数的。

h的实际类型为HandlerFunc,根据2.2.2会调用到具体函数timeHandler或者helloHandler

3. 总结

golang对socket编程进行了封装,给HTTP编程带来了极大的便利。

但是不支持一下特性

1. 路由分组 对路由进行分组,可以方便分组鉴权

2. 动态路由 如动态路由/user/:username/post/:postid不支持

Golang HTTP编程及源码解析的更多相关文章

  1. golang的flag包源码解析与使用

    当我们 import  package时,package内的全局常量和全局变量会进行初始化,并且紧接着init函数会执行.因此我们先看一下flag包的全局常量和全局变量. 一.flag包的全局常量.全 ...

  2. 【Java源码解析】Thread

    简介 线程本质上也是进程.线程机制提供了在同一程序内共享内存地址空间运行的一组线程.对于内核来讲,它就是进程,只是该进程和其他一下进程共享某些资源,比如地址空间.在Java语言里,Thread类封装了 ...

  3. MyBatis源码解析【7】接口式编程

    前言 这个分类比较连续,如果这里看不懂,或者第一次看,请回顾之前的博客 http://www.cnblogs.com/linkstar/category/1027239.html 修改例子 在我们实际 ...

  4. 【Android编程】android平台的MITM瑞士军刀_cSploit源码解析及中间人攻击复现

    /文章作者:Kali_MG1937 作者博客ID:ALDYS4 QQ:3496925334 未经允许,禁止转载/ 何为MITM欺骗,顾名思义,中间人攻击的含义即为在局域网中充当数据包交换中间人的角色 ...

  5. Spring IoC源码解析——Bean的创建和初始化

    Spring介绍 Spring(http://spring.io/)是一个轻量级的Java 开发框架,同时也是轻量级的IoC和AOP的容器框架,主要是针对JavaBean的生命周期进行管理的轻量级容器 ...

  6. 源码解析-Volley(转自codeKK)

    Volley 源码解析 本文为 Android 开源项目源码解析 中 Volley 部分项目地址:Volley,分析的版本:35ce778,Demo 地址:Volley Demo分析者:grumoon ...

  7. jQuery整体架构源码解析(转载)

    jQuery整体架构源码解析 最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性, ...

  8. String,StringBuffer和StringBuilder源码解析[基于JDK6]

    最近指导几位新人,学习了一下String,StringBuffer和StringBuilder类,从反馈的结果来看,总体感觉学习的深度不够,没有读出东西.其实,JDK的源码是越读越有味的.下面总结一下 ...

  9. kubernetes源码解析---- apiserver路由构建解析(1)

    kubernetes源码解析---- apiserver路由构建解析(1) apiserver作为k8s集群的唯一入口,内部主要实现了两个功能,一个是请求的路由和处理,简单说就是监听一个端口,把接收到 ...

  10. Retrofit2 源码解析

    原文链接:http://bxbxbai.github.io/2015/12/13/retrofit2-analysis/ 公司里最近做的项目中网络框架用的就是Retrofit,用的多了以后觉得这个框架 ...

随机推荐

  1. VS 新版本无法打开旧项目问题处理

    问题 最近想阅读 WorkflowCore 的源码,苦于代码量巨大,就想将项目回退到 Init Commit 版本 但是在回退版本后,工程内Project 显示已卸载 重新加载后 提示: 不支持 Th ...

  2. (GCC) gcc 编译选项 -fno-omit-frame-pointer,-fno-tree-vectorize,fno-optimize-sibling-calls;及内存泄漏、非法访问检测 ASAN

    omit-frame-pointer 开启该选项,主要是用于去掉所有函数SFP(Stack Frame Pointer)的,即在函数调用时不保存栈帧指针SFP,代价是不能通过backtrace进行调试 ...

  3. ArcGIS 添加Excel数据 报错 ArcGIS Failed to connect to database 外部数据库驱动程序(1)中的意外错误

    原因是因为 操作系统安装了一些补丁,卸载即可. 把以下补丁卸载掉即可. win7 <-- KB4041678 , KB4041681  --> SERVER 2008 R2 <-- ...

  4. Microsoft.IO.RecyclableMemoryStream源码解读

    一.RecyclableMemoryStreamManager 源码地址:https://github.com/Microsoft/Microsoft.IO.RecyclableMemoryStrea ...

  5. (小白向)2020-12-18 中国大学MOOC第十二讲-动态变量应用

    1创建单向链表(10分) 问题描述:根据随机输入的若干非零整数,以数字0结束:建立一个新链表. 输入:随机输入若干个整数,以数字0结束 输出:新建链表中个节点的值,数字间没有间隔字符. 样例:输入 5 ...

  6. SQLMap自带绕过脚本tamper的讲解

      sqlmap在默认情况下除了使用CHAR()函数防止出现单引号,没有对注入的数据进行修改,还可以使用--tamper参数对数据做修改来绕过WAF等设备,其中大部分脚本主要用正则模块替代攻击载荷字符 ...

  7. 图解B树及C#实现(2)数据的读取及遍历

    目录 前言 查询数据 算法说明 代码实现 查询最值 算法说明 代码实现 B树的遍历 算法说明 代码实现 Benchmarks 总结 参考资料 前言 本文为系列文章 B树的定义及数据的插入 数据的读取及 ...

  8. vscode问题:由于找不到ffmpag.dll文件,无法继续执行代码

    工作中发现VS code打不开了,显示如下:  解决方法: 一.打开Microsoft VS Code 文件夹,发现一部分文件被打包进了一个叫"_"的文件夹(第一个)  二.把该文 ...

  9. python之路46 django request对象 form表单 pycharm连接数据库 ORM简介

    静态文件配置 1.编写一个用户登录页面 2.静态文件 不怎么经常变化的文件 主要针对html文件所使用的到的各种资源 css文件.js文件.img文件.第三方框架文件 django针对静态文件资源需要 ...

  10. Hash——温暖人心的算法

    目录 简介 计算Hash 前缀Hash递推 快速计算子串Hash 用Hash匹配字符串 综合:P2852 [USACO06DEC]Milk Patterns G 简介 Hash,将一个字符串映射到一个 ...