Go学习(二十):启动HTTP服务的方式
1. 怎么启动Web服务?
Go
语言标准库内置的net/http
包,可以实现HTTP
服务端。实现HTTP
服务端就是能够启动Web
服务,相当于搭建起了一个Web
服务器。 http.ListenAndServer()
函数用来启动Web
服务,绑定并监听http
端口。
func ListenAndServe(addr string, handler Handler)// addr:监听地址;如 :8080 或者0.0.0.0:8080// handler:HTTP处理器Handler
2.启动Web服务的几种方式
根据不同服务返回的handler
,常见启动Web
服务有以下几种方式。
2.1 http.FileServer: 静态文件服务
http.FileServer()
搭建的服务器只提供静态文件的访问。因为这种web
服务只支持静态文件访问,所以称之为静态文件服务。
1.使用示例
文件目录如下:
package mainimport ( "net/http")func main() { runFileServer()}// 启动一个文件服务器func runFileServer() { // 如果改路径下有index.html,则会优先显示index.html,否则会看到文件目录 http.ListenAndServe(":3000",http.FileServer(http.Dir("./public/")))}
注意: 启动的时候,需求使用go run main.go。否则会报404
2.2 http.HandleFunc: 默认的多路由分发服务
http.HandleFunc()
的作用是注册网络访问的路由。因为它采用的是默认的路由分发任务方式,所以称之为默认的多路由分发服务。
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) { DefaultServeMux.HandleFunc(pattern, handler)}// pattern:请求路径的匹配模式// handler:函数类型,表示这个请求需要处理的事情,其实就是Handler接口中的ServeHTTP()方法。
ServeHTTP()
方法有两个参数,其中第一个参数是ResponseWriter
类型,包含了服务器端给客户端的响应数据。服务器端往ResponseWriter
写入了什么内容,浏览器的网页源码就是什么内容。第二个参数是一个*Request
指针,包含了客户端发送给服务器端的请求信息(路径、浏览器类型等)
1.使用示例
package mainimport ( "fmt" "net/http")func main() { // 绑定路由/hello http.HandleFunc("/hello",helloHandle) // 绑定路由到/test http.HandleFunc("/test",testHandle) // 启动服务 err := http.ListenAndServe(":5000",nil) fmt.Println(err)}// 处理路由hellofunc helloHandle(w http.ResponseWriter, r *http.Request) { fmt.Println("访问路由hello") // 解析url参数 fmt.Println(r.URL.Query()) w.Write([]byte("hello word!"))}// 处理路由testfunc testHandle(w http.ResponseWriter, r *http.Request) { fmt.Println("访问路由test") // 解析url参数,并输出 fmt.Println(r.URL.Query()) w.Write([]byte("test doing!"))}// 访问: http://127.0.0.1:5000/test?a=1001// 访问: http://127.0.0.1:5000/hello?b=990
通过
http. HandleFunc()
注册网络路由时,http.ListenAndServer()
的第二个参数通常为nil
,这意味着服务端采用默认的http.DefaultServeMux
进行分发处理。
2.3 http.NewServeMux(): 自定义多路由分发服务
http.NewServeMux()
的作用是注册网络访问的多路路由。因为它采用的是自定义的多路由分发任务方式,所以称之为自定义多路由分发服务。
注册网络路由时,如果http.ListenAndServer()
的第二个参数为nil
,那么表示服务端采用默认的http.DefaultServeMux
进行分发处理。也可以自定义ServeMux
。ServeMux
结构体如下
// ServeMux结构体源码type ServeMux struct { mu sync.RWMutex // 锁,由于请求涉及到并发处理,因此这里有个锁机制 m map[string]muxEntry // 存放具体的路由信息 es []muxEntry // 按照路由长度从大到小的存放处理函数 hosts bool // 标记路由中是否带有主机名}// muxEntry是路由的具体条目type muxEntry struct { h Handler // 处理函数 pattern string // 路由路径}
3. 自定义多路由实践
package mainimport ( "fmt" "net/http")// 定义一个接口体,用来实现http.Handlertype MyRoute struct {}// 实现http.Handler接口中的ServeHTTP方法func (m *MyRoute)ServeHTTP(w http.ResponseWriter,r *http.Request) { path := r.URL.Path fmt.Println(path) switch path { case "/": w.Write([]byte("首页")) case "/hello": w.Write([]byte("say hello")) case "/test": w.Write([]byte("test doing")) default: http.NotFound(w,r) } return}func main() { myRoute := &MyRoute{} http.ListenAndServe(":10000",myRoute)}
3.1 代码执行流程
使用http.ListenAndServe(":10000",myRoute)
启动服务之后,会发生以下操作
1.实例化http.Server
,并调用ListenAndServe()
func ListenAndServe(addr string, handler Handler) error { // 实例化 Server server := &Server{Addr: addr, Handler: handler} // 调用 ListenAndServe() return server.ListenAndServe()}
2.监听端口
func (srv *Server) ListenAndServe() error { if srv.shuttingDown() { return ErrServerClosed } addr := srv.Addr if addr == "" { addr = ":http" } // 监听端口 ln, err := net.Listen("tcp", addr) if err != nil { return err } // 启动服务 return srv.Serve(ln) }
3.启动for无限循环,在循环体中Accept
请求,并开启 goroutine
为这个请求服务
func (srv *Server) Serve(l net.Listener) error { //...省略N行代码 for { rw, err := l.Accept() if err != nil { //...省略N行代码 } connCtx := ctx if cc := srv.ConnContext; cc != nil { connCtx = cc(connCtx, rw) if connCtx == nil { panic("ConnContext returned nil") } } tempDelay = 0 c := srv.newConn(rw) c.setState(c.rwc, StateNew) // 开启goroutine为这个请求服务 go c.serve(connCtx) }}
4.读取每个请求内容,并调用ServeHTTP
func (c *conn) serve(ctx context.Context) { //...省略N行代码 for { // 读取每个请求内容 w, err := c.readRequest(ctx) //...省略N行代码
// 调用ServeHTTP serverHandler{c.server}.ServeHTTP(w, w.req) //...省略N行代码}
5. 判断handler
是否为空,如果为空则把handler
设置成DefaultServeMux
。
func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) { handler := sh.srv.Handler if handler == nil { // 如果为空则把handler设置成DefaultServeMux。 handler = DefaultServeMux } if req.RequestURI == "*" && req.Method == "OPTIONS" { handler = globalOptionsHandler{} } // 上述示例中,传的是&MyRoute,所以会调用MyRoute.ServeHTTP handler.ServeHTTP(rw, req)}
微信搜索关注【猿码记】查看更多文章。
本文由 mdnice 多平台发布
Go学习(二十):启动HTTP服务的方式相关推荐
- linux samba 服务端口号,Linux系统学习 二十、SAMBA服务—介绍、安装、端口
1.简介 网络数据文件共享服务器 可以和Windows中的网上邻居通用 数据共享的方法: Windows中最常用的是"网上邻居".网上邻居使用的文件系统是CIFS(通用互联网文件系 ...
- SAP UI5 初学者教程之二十六 - OData 服务配合 Mock 服务器的使用步骤详解试读版
一套适合 SAP UI5 初学者循序渐进的学习教程 教程目录 SAP UI5 本地开发环境的搭建 SAP UI5 初学者教程之一:Hello World SAP UI5 初学者教程之二:SAP UI5 ...
- OpenCV学习(二十) :分水岭算法:watershed()
OpenCV学习(二十) :分水岭算法:watershed() 参考博客: OpenCV-分水岭算法 图像处理--分水岭算法 OpenCV学习(7) 分水岭算法(1) Opencv分水岭算法--wat ...
- OpenCV学习(二十四 ):角点检测(Corner Detection):cornerHarris(),goodFeatureToTrack()
OpenCV学习(二十四 ):角点检测(Corner Detection):cornerHarris(),goodFeatureToTrack() 参考博客: Harris角点检测原理详解 Harri ...
- OpenCV学习(二十二) :反向投影:calcBackProject(),mixChannels()
OpenCV学习(二十二) :反向投影:calcHist(),minMaxLoc(),compareHist() 参考博客: 反向投影backproject的直观理解 opencv 反向投影 颜色直方 ...
- PyTorch框架学习二十——模型微调(Finetune)
PyTorch框架学习二十--模型微调(Finetune) 一.Transfer Learning:迁移学习 二.Model Finetune:模型的迁移学习 三.看个例子:用ResNet18预训练模 ...
- C1认证学习二十六(基础选择器)
C1认证学习二十六(基础选择器) 任务背景 CSS选择器是CSS规则的一部分,用来指定需要设置的样式的HTML元素,通过选择器可以实现CSS对HTML元素一对一或者一对多或者多对一的控制了啦. 任务目 ...
- 知识图谱论文阅读(八)【转】推荐系统遇上深度学习(二十六)--知识图谱与推荐系统结合之DKN模型原理及实现
学习的博客: 推荐系统遇上深度学习(二十六)–知识图谱与推荐系统结合之DKN模型原理及实现 知识图谱特征学习的模型分类汇总 知识图谱嵌入(KGE):方法和应用的综述 论文: Knowledge Gra ...
- VUE学习(二十)、插槽
VUE学习(二十).插槽 一.默认插槽 1.Category.vue <template><div class="category"><h3>{ ...
最新文章
- 报名 | 数据新闻发展趋势与人才培养学术讲座(武汉)
- (转载)一种根据纠偏数据对火星坐标进行完美拟合的方法
- Struts2中的配置文件--struts.properties文件
- lodoop打印控件详解
- [转载]jquery cookie的用法
- STM32的map文件学习笔记
- 三维叉乘怎么算_3分钟做完这些题,你的CAD才算熟练
- (12)Verilog HDL变量:reg型
- php fpm listen.owner,nginx 与 php-fpm socket 所有者权限问题
- antd 设置表头属性_React表格固定表头/锁定列
- oracle批量造测试数据
- Mysql安装(转自韩顺平教育)
- Win7 获取管理员权限
- 用java求水仙花数,适合新手
- 1014 福尔摩斯的约会 (20 分)
- 阴阳师召唤式神app(安卓)
- 26. SAP ABAP OData Gateway 框架里 /IWFND, /IWBEP 这些缩写代表了什么含义?
- 【PyTorch深度学习实践】08_Softmax分类器(多分类)
- 关于如何在WPS中生成附图索引
- 少儿编程值得报班学习吗?别问了,程序员懵了