net/http标准库

net/http标准库通常包括两个部分,客户端和服务器,我们可以通过ListenAndServe创建一个简陋的服务器

package main

import (
"net/http"
) func main() {
http.ListenAndServe("", nil)
}

这会使用默认的80端口进行网络连接,并且使用默认的多路复用器DefaultServeMux,我们也可以通过Server结构进行更详细的配置

func main() {
server := http.Server {
Addr: "127.0.0.1:80",
Handler: nil,
}
server.ListenAndServe()
}

处理器和处理函数

处理器

前面的代码会返回404响应,因为我们还没有为请求编写相应的处理器。一个处理器就是一个拥有ServeHTTPf方法的接口

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

我们通过实现这个接口来编写处理器

type MyHandler struct{}

func (h *MyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, world")
} func main() {
handler := MyHandler{}
server := http.Server {
Addr: "127.0.0.1:80",
Handler: &handler,
}
server.ListenAndServe()
}

我们可以设置多个处理器

type HelloHandler struct{}

func (hello *HelloHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "hello!")
} type WorldHandler struct{} func (world *WorldHandler) ServeHTTP(w http.ResponseWriter, r *http.Reuest) {
fmt.Fprintf(w, "world!")
} func main() {
hello := HelloHandler{}
world := WorldHandler{} server := http.Server {
Addr: "127.0.0.1:80",
}
http.Handle("/hello", &hello)
http.Handle("/world", &world) server.ListenAndServe()
}

我们看一下Handle函数再源码中的定义

func Handle(pattern string, handler Handler) {
DefaultServeMux.Handle(pattern, handler)
}

实际上是在调用DefaultServeMux的某个方法,前面我们已经提到过了DefaultServeMux是个默认多路复用器,实际上它也是个Handler处理器,因为他是ServeMux结构的一个实例,而ServeMux也实现了Handler接口的ServeHTTP方法。这样就可以对不同的请求做出不同的响应。

处理器函数

处理器函数是与处理器拥有同样行为的函数,它们与ServeHTTP拥有同样的函数签名。

func hello (w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello!")
} func main() {
server := http.Server {
Addr: "127.0.0.1:8080",
}
http.HandleFunc("/hello", hello) server.ListenAndServe()
}

HandleFunc是Go语言拥有的一种函数类型,它可以把一个带有正确签名的f转换为带有方法f的handler。

来看看HandleFunc的源码

func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
DefaultServeMux.HandleFunc(pattern, handler)
} func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
if handler == nil {
panic("http: nil handler")
}
mux.Handle(pattern, HandlerFunc(handler))
}

Handle函数是不是似曾相识!

串联多个处理器和处理器函数

func hello(w *http.ResponseWriter, r *Request) {
fmt.Fprintf(w, "Hello!")
} func log(h http.Handler) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
fmt.Println("Log!")
h(w, r)
}
} func main() {
server := http.Server {
Addr: "127.0.0.1:8080",
}
http.HandleFunc("/hello", log(hello))
server.ListenAndServe()
}

其中HandlerFunc是实现了Handler接口的函数类型,源码定义:

type HandlerFunc func(ResponseWriter, *Request)

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

ServeMux

ServeMux是一个HTTP请求多路复用器,负责接收HTTP请求并根据请求中的URL将请求重定向到正确的处理器。ServeMux包含一个映射,这个映射会将URL映射至相应的处理器。值得一提的是,ServeMux无法使用变量实现URL模式匹配,因此必要时我们完全可以用其它自建的多路复用器来代替ServeMux,如HttpRouter等高效轻量的第三方复用器

Go Web编程 第三章--接收请求的更多相关文章

  1. Go Web编程 第四章--处理请求

    请求和响应 Request结构 URL字段 Header字段 Body字段 Form, PostForm, MultipartForm字段 在处理器函数中,我们可以通过Request获取各个字段的详细 ...

  2. [转]Windows Shell 编程 第三章 【转自:http://blog.csdn.net/wangqiulin123456/article/details/7987901】

    第三章 操作文件 我依然清楚地记得,Windows95 的贝塔版出现的情形,它在朋友之间和学院中传播,好酷,全新的文件管理器,一种全图标,全彩色可客户化的界面,以及活泼的动画标识使得在文件拷贝和删除方 ...

  3. 读高性能JavaScript编程 第三章

    第三章  DOM Scripting  最小化 DOM 访问,在 JavaScript 端做尽可能多的事情. 在反复访问的地方使用局部变量存放 DOM 引用. 小心地处理 HTML 集合,因为他们表现 ...

  4. Windows核心编程 第三章 内核对象

    第3章内核对象 在介绍Windows API的时候,首先要讲述内核对象以及它们的句柄.本章将要介绍一些比较抽象的概念,在此并不讨论某个特定内核对象的特性,相反只是介绍适用于所有内核对象的特性. 首先介 ...

  5. windows核心编程---第三章 内核对象及句柄本质

      本章讨论的是相对抽象的概念,不涉及任何具体的内核对象的细节而是讨论所有内核对象的共有特性. 首先让我们来了解一下什么是内核对象.内核对象通过API来创建,每个内核对象是一个数据结构,它对应一块内存 ...

  6. 【1】python核心编程 第三章

    1.继续( \ ) 有两种例外情况一个语句不使用反斜线也可以跨行.在使用闭合操作符时,单一语句可以跨多行,例如:在含有小括号.中括号.花括号时可以多行书写.另外就是三引号包括下的字符串也可以跨行书写 ...

  7. python核心编程-第三章-个人笔记

    1.语句和语法 (1)反斜杠"\"表示语句继续.python良好的编程习惯是一行最后不超过80个字符,一行字符过多时便须用到反斜杠换行继续该语句. PS:在使用小括号.中括号.大括 ...

  8. JavaWeb核心编程之(三.5)HTTP请求和接受表单数据

    HTTP简介WEB浏览器与WEB拂去其之间的一问一答的交互过程, 必须遵循一定的规则,这个规则就是HTTP协议HTTP是hypertext transfer protocol(超文本传输协议)的简写, ...

  9. WEB安全第三篇--控制请求的艺术:CSRF和SSRF

    零.前言 最近做专心web安全有一段时间了,但是目测后面的活会有些复杂,涉及到更多的中间件.底层安全.漏洞研究与安全建设等越来越复杂的东东,所以在这里想写一个系列关于web安全基础以及一些讨巧的pay ...

随机推荐

  1. jQuery Validate自定义金钱验证,是否为金额格式,保留两位小数,并支持千分制货币格式

    //自定义函数实现 isMoney: function (value, element){ // return this.optional(element) || /(^[1-9]([0-9]+)?( ...

  2. 【工具记录】Linux口令破解

    1.基础知识 /etc/passwd:记录着用户的基本属性,所有用户可读 字段含义如下: 用户名:口令:用户标识号:组标识号:注释性描述:主目录:登录Shell eg: root:x:0:0:root ...

  3. a标签、img图片、iframe、表单元素、div

    1.<a href="http://www.baidu.com" target=''_blank">百度</a>  超链接标签 2.<img ...

  4. Python爬虫之三种网页抓取方法性能比较

    下面我们将介绍三种抓取网页数据的方法,首先是正则表达式,然后是流行的 BeautifulSoup 模块,最后是强大的 lxml 模块. 1. 正则表达式   如果你对正则表达式还不熟悉,或是需要一些提 ...

  5. Java数据类型以及变量的定义

    1130136248   Java的基本数据类型 变量就是申请内存来存储值.也就是说,当创建变量的时候,需要在内存中申请空间. 内存管理系统根据变量的类型为变量分配存储空间,分配的空间只能用来储存该类 ...

  6. python并行计算(持续更新)

    工作中需要对tensorflow 的一个predict结果加速,利用python中的线程池 def getPPLs(tester,datas): for line in datas: tester(l ...

  7. 怎么使用T-sql生成两位字母

    SQL code select char(cast(rand()*25 as int)+97)+char(cast(rand()*25             as int)+97) select 两 ...

  8. Oracle学习笔记:trunc函数

    在Oracle中可以使用trunc函数进行日期截取和数字截取,具体使用方法如下: 1.trunc(for dates) 日期截取 语法:trunc(date,[fmt]) select trunc(s ...

  9. MySQL学习笔记:调用存储过程或函数报1418错误

    问题 MySQL开启bin-log后,调用存储过程或者函数以及触发器时,会出现错误号为1418的错误: ERROR 1418 (HY000): This function has none of DE ...

  10. NOIP2018初赛 解题报告(C++普及)

    第24届全国青少年信息学奥林匹克联赛初赛 普及组C++语言试题 竞赛时间:2018 年 10 月 13 日 14:30~16:30 选手注意: 1.试题纸共有 7 页,答题纸共有 2 页,满分 100 ...