简介
go提供了一系列用于创建web服务器的标准库,而且通过go创建一个服务器的步骤非常简单,只要通过 net/http包调用 ListenAndServe函数并传入网络地址以及负责处理请求的处理器(handler)作为参数就可以了。如果网络地址参数为空字符串,那么服务器默认使用80端口进行网络连接;如果处理器参数为nil, 那么服务器将使用默认的多路复用器DefaultServeMux,当然,也可以通过调用NewServeMux函数创建一个多路复用器。多路复用器接收到用户的请求之后根据请求的URL来判断使用哪个处理器来处理请求,找到后就会重定向到对应的处理器来处理请求
默认的多路复用器(DefaultServeMux)
- 使用处理器函数处理请求
package main
import (
"fmt"
"net/http"
)
//创建处理器函数
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "正在通过处理器函数处理你的请求")
}
func main() {
http.HandleFunc("/", handler)
//创建路由
http.ListenAndServe(":8080", nil)
}
- func HandleFunc
func HandleFunc(pattern string, handler func(ResponseWriter, *Request))
HandleFunc注册一个处理器函数handler和对应的模式pattern(注册到DefaultServeMux)。ServeMux的文档解释了模式的匹配机制
处理器函数的实现原理
- go语言拥有一种HandlerFunc函数类型,它可以将一个带有正确签名的函数 f 转换成一个带有方法 f 的Handler
type HandlerFunc
type HandlerFunc func(ResponseWriter, *Request)
HandlerFunc type是一个适配器,通过类型转换让我们可以将普通的函数作为HTTP处理器使用。如果f是一个具有适当签名的函数,HandlerFunc(f)通过调用f实现了Handler接口
- 使用处理器处理请求
package main
import (
"fmt"
"net/http"
)
type MyHandler struct {
}
func (m *MyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "通过自己创建的处理器处理请求!")
}
func main() {
myHandler := MyHandler{}
http.Handle("/myHandler", &myHandler)
http.ListenAndServe(":8080", nil)
}
浏览器访问
http://127.0.0.1:8080/myHandler
- func Handle
func Handle(pattern string, handler Handler)
Handle注册HTTP处理器handler和对应的模式pattern(注册到DefaultServeMux)。如果该模式已经注册有一个处理器,Handle会panic。ServeMux的文档解释了模式的匹配机制
- type Handler
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
实现了Handler接口的对象可以注册到HTTP服务端,为特定的路径及其子树提供服务
ServeHTTP应该将回复的头域和数据写入ResponseWriter接口然后返回。返回标志着该请求已经结束,HTTP服务端可以转移向该连接上的下一个请求
只要某个结构体实现了 Handler接口中的 ServeHTTP方法,那么它就是一个处理器
- 通过Server结构对服务器进行更详细的配置
- type Server
type Server struct {
Addr string // 监听的TCP地址,如果为空字符串会使用":http"
Handler Handler // 调用的处理器,如为nil会调用http.DefaultServeMux
ReadTimeout time.Duration // 请求的读取操作在超时前的最大持续时间
WriteTimeout time.Duration // 回复的写入操作在超时前的最大持续时间
MaxHeaderBytes int // 请求的头域最大长度,如为0则用DefaultMaxHeaderBytes
TLSConfig *tls.Config // 可选的TLS配置,用于ListenAndServeTLS方法
// TLSNextProto(可选地)指定一个函数来在一个NPN型协议升级出现时接管TLS连接的所有权。
// 映射的键为商谈的协议名;映射的值为函数,该函数的Handler参数应处理HTTP请求,
// 并且初始化Handler.ServeHTTP的*Request参数的TLS和RemoteAddr字段(如果未设置)。
// 连接在函数返回时会自动关闭。
TLSNextProto map[string]func(*Server, *tls.Conn, Handler)
// ConnState字段指定一个可选的回调函数,该函数会在一个与客户端的连接改变状态时被调用。
// 参见ConnState类型和相关常数获取细节。
ConnState func(net.Conn, ConnState)
// ErrorLog指定一个可选的日志记录器,用于记录接收连接时的错误和处理器不正常的行为。
// 如果本字段为nil,日志会通过log包的标准日志记录器写入os.Stderr。
ErrorLog *log.Logger
// 内含隐藏或非导出字段
}
Server类型定义了运行HTTP服务端的参数。Server的零值是合法的配置
package main
import (
"fmt"
"net/http"
"time"
)
type MyHandler struct {
}
func (m *MyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "通过详细配置服务器的信息来处理请求!")
}
func main() {
myHandler := MyHandler{}
//创建Server结构,并详细配置
server := http.Server{
Addr: ":8080",
Handler: &myHandler,
ReadTimeout: 2 * time.Second,
}
server.ListenAndServe()
}
使用自己创建的多路复用器
- 在创建服务器时,还可以通过 NewServeMux方法创建一个多路复用器
func NewServeMux
func NewServeMux() *ServeMux
NewServeMux创建并返回一个新的*ServeMux
package main
import (
"fmt"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "通过自己创建的多路复用器来处理请求")
}
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/myMux", handler)
http.ListenAndServe(":8080", mux)
}
结构体ServeMux
type ServeMux
type ServeMux struct {
// 内含隐藏或非导出字段
}
ServeMux类型是HTTP请求的多路转接器。它会将每一个接收的请求的URL与一个注册模式的列表进行匹配,并调用和URL最匹配的模式的处理器。
模式是固定的、由根开始的路径,如"/favicon.ico",或由根开始的子树,如"/images/"(注意结尾的斜杠)。较长的模式优先于较短的模式,因此如果模式"/images/“和”/images/thumbnails/“都注册了处理器,后一个处理器会用于路径以”/images/thumbnails/“开始的请求,前一个处理器会接收到其余的路径在”/images/"子树下的请求。
注意,因为以斜杠结尾的模式代表一个由根开始的子树,模式"/“会匹配所有的未被其他注册的模式匹配的路径,而不仅仅是路径”/"。
模式也能(可选地)以主机名开始,表示只匹配该主机上的路径。指定主机的模式优先于一般的模式,因此一个注册了两个模式"/codesearch"和"codesearch.google.com/"的处理器不会接管目标为"http://www.google.com/"的请求。
ServeMux还会注意到请求的URL路径的无害化,将任何路径中包含".“或”…"元素的请求重定向到等价的没有这两种元素的URL。(参见path.Clean函数)
结构体ServeMux 相关方法
- func (*ServeMux) Handle
func (mux *ServeMux) Handle(pattern string, handler Handler)
Handle注册HTTP处理器handler和对应的模式pattern。如果该模式已经注册有一个处理器,Handle会panic。
- func (*ServeMux) HandleFunc
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request))
HandleFunc注册一个处理器函数handler和对应的模式pattern。
- func (*ServeMux) Handler
func (mux *ServeMux) Handler(r *Request) (h Handler, pattern string)
Handler根据r.Method、r.Host和r.URL.Path等数据,返回将用于处理该请求的HTTP处理器。它总是返回一个非nil的处理器。如果路径不是它的规范格式,将返回内建的用于重定向到等价的规范路径的处理器。
Handler也会返回匹配该请求的的已注册模式;在内建重定向处理器的情况下,pattern会在重定向后进行匹配。如果没有已注册模式可以应用于该请求,本方法将返回一个内建的"404 page not found"处理器和一个空字符串模式。
- func (*ServeMux) ServeHTTP
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request)
ServeHTTP将请求派遣到与请求的URL最匹配的模式对应的处理器