Golang net/http知识讲解

如下是对net/http的学习。浏览器

Go 语言中处理 HTTP 请求主要跟两个东西相关:ServeMux 和 Handler。 ServrMux 本质上是一个 HTTP 请求路由器(或者叫多路复用器,Multiplexor)。它把收到的请求与一组预先定义的 URL 路径列表作对比,而后在匹配到路径的时候调用关联的处理器(Handler)。服务器

处理器(Handler)负责输出HTTP响应的头和正文。任何知足了http.Handler接口的对象均可做为一个处理器。通俗的说,对象只要有个以下签名的ServeHTTP方法便可:闭包

ServeHTTP(http.ResponseWriter, *http.Request)

Go 语言的 HTTP 包自带了几个函数用做经常使用处理器,好比FileServer,NotFoundHandler 和 RedirectHandler。咱们从一个简单具体的例子开始:函数

package main

import (
	"log"
	"net/http"
)

func main() {
	mux := http.NewServeMux()

	rh := http.RedirectHandler("http://www.baidu.com", 307)
	mux.Handle("/foo", rh)

	log.Println("Listening...")
	http.ListenAndServe(":3000", mux)
}

快速地过一下代码:学习

在 main 函数中咱们只用了 http.NewServeMux 函数来建立一个空的 ServeMux。 而后咱们使用 http.RedirectHandler 函数建立了一个新的处理器,这个处理器会对收到的全部请求,都执行307重定向操做到 http://www.baidu.com。 接下来咱们使用 ServeMux.Handle 函数将处理器注册到新建立的 ServeMux,因此它在 URL 路径/foo 上收到全部的请求都交给这个处理器。 最后咱们建立了一个新的服务器,并经过 http.ListenAndServe 函数监听全部进入的请求,经过传递刚才建立的 ServeMux来为请求去匹配对应处理器。code

而后在浏览器中访问 http://localhost:3000/foo 你应该能发现请求已经成功的重定向了。orm

明察秋毫的你应该能注意到一些有意思的事情:ListenAndServer 的函数签名是 ListenAndServe(addr string, handler Handler) ,可是第二个参数咱们传递的是个 ServeMux。对象

咱们之因此能这么作,是由于 ServeMux 也有 ServeHTTP 方法,所以它也是个合法的 Handler。接口

对我来讲,将 ServerMux 用做一个特殊的Handler是一种简化。它不是本身输出响应而是将请求传递给注册到它的其余 Handler。这乍一听起来不是什么明显的飞跃 - 但在 Go 中将 Handler 链在一块儿是很是广泛的用法。ip

自定义处理器(Custom Handlers)

真正的重点是咱们有一个对象(本例中就是个timerHandler结构体,可是也能够是一个字符串、一个函数或者任意的东西),咱们在这个对象上实现了一个 ServeHTTP(http.ResponseWriter, *http.Request) 签名的方法,这就是咱们建立一个处理器所需的所有东西。

package main

import (
	"log"
	"net/http"
	"time"
)

type timeHandler struct {
	format string
}

func (th *timeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	tm := time.Now().Format(th.format)
	w.Write([]byte("The time is : " + tm))
}

func main() {
	mux := http.NewServeMux()

	rh := http.RedirectHandler("http://www.baidu.com", 307)
	th := &timeHandler{format: time.RFC1123}

	mux.Handle("/a", rh)
	mux.Handle("/time", th)

	log.Println("Listening.....")
	http.ListenAndServe(":3000", mux)

}

将函数做为处理器

http.HandlerFunc()可以让一个常规函数做为一个Handler接口条件

func timeHandler(w http.ResponseWriter, r *http.Request) {
	tm := time.Now().Format(time.RFC1123)
	w.Write([]byte("the time is : " + tm))
}

func main() {
	mux := http.NewServeMux()

	rh := http.RedirectHandler("http://www.baidu.com", 307)
	th := http.HandlerFunc(timeHandler)

	mux.Handle("/a", rh)
	mux.Handle("/time", th)

	log.Println("Listening.....")
	http.ListenAndServe(":3000", mux)

}

更为便捷的方式:ServerMux.HandlerFunc 方法

func main() {
	mux := http.NewServeMux()

	mux.HandleFunc("/time", timeHandler)

	log.Println("Listening...")
	http.ListenAndServe(":3000", mux)
}

若是方法中须要参数,则须要使用闭包,将变量带入:

//demo1
 func timeHandler(format string) http.Handler{
	fn:=func(w http.ResponseWriter,r *http.Request){
		tm:=time.Now().Format(format)
		w.Write([]byte("The time is : "+tm))
	}

	 return http.HandlerFunc(fn)
 }
 //demo2
 func timeHandler(format string) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		tm := time.Now().Format(format)
		w.Write([]byte("The time is: " + tm))
	})
}
//demo3
func timeHandler(format string) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		tm := time.Now().Format(format)
		w.Write([]byte("The time is: " + tm))
	}
}

更为便利的DefaultServeMux

net/http 包提供了一组快捷方式来配合 DefaultServeMux:http.Handle 和 http.HandleFunc。这些函数与咱们以前看过的相似的名称的函数功能同样,惟一的不一样是他们将处理器注册到 DefaultServerMux ,而以前咱们是注册到本身建立的 ServeMux。

此外,ListenAndServe在没有提供其余的处理器的状况下(也就是第二个参数设成了 nil),内部会使用 DefaultServeMux。

所以,做为最后一个步骤,咱们使用 DefaultServeMux 来改写咱们的 timeHandler应用:

func timeHandler(format string) http.Handler {
	fn := func(w http.ResponseWriter, r *http.Request) {
		tm := time.Now().Format(format)
		w.Write([]byte("The time is : " + tm))
	}

	return http.HandlerFunc(fn)
}

func main() {
	/* mux := http.NewServeMux()

	rh := http.RedirectHandler("http://www.baidu.com", 307)
	th := timeHandler(time.RFC1123)

	mux.Handle("/a", rh)
	mux.Handle("/time", th)

	log.Println("Listening.....")
	http.ListenAndServe(":3000", mux)
	*/

	var format string = time.RFC1123

	th := timeHandler(format)

	http.Handle("/time", th)

	log.Println("listening....")

	http.ListenAndServe(":3000", nil)
}
相关文章
相关标签/搜索