Golang — net/http简介

go web示例

我们以下面的示例介绍golang的net/http包的简单使用。

package main

import "net/http"
	
func main() {
    
    
	http.HandleFunc("/", helloWord)  // 注册处理器
	http.ListenAndServe(":8888", nil) // 监听8888端口,启动web项目
}

func helloWorld(rw http.ResponseWriter, r *http.Request) {
    
    
	rw.Write([]byte("Hello, World!"))
}

http.HandleFunc

http.HandleFuncDefaultServeMux中注册一个handler。
DefaultServeMux是go默认提供的ServeMux

// HandleFunc registers the handler function for the given pattern
// in the DefaultServeMux.
// The documentation for ServeMux explains how patterns are matched.
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
    
    
	DefaultServeMux.HandleFunc(pattern, handler)
}

DefaultServeMux:
当我们没有创建ServeMux变量时,会使用这个默认创建的。

// DefaultServeMux is the default ServeMux used by Serve.
var DefaultServeMux = &defaultServeMux

var defaultServeMux ServeMux

ServeMux

ServeMux 是一个http请求的多路复用器。从请求路径到handler的映射全部存在一个map数据类型的属性里,即ServeMux.m

// ServeMux 是一个http请求的多路复用器.
type ServeMux struct {
    
    
	mu    sync.RWMutex
	m     map[string]muxEntry
	es    []muxEntry // contains all patterns that end in / sorted from longest to shortest.
	hosts bool       // whether any patterns contain hostnames
}

type muxEntry struct {
    
    
	h       Handler
	pattern string
}

我们接着看上一节中的DefaultServeMux.HandleFunc(pattern, handler)方法:
该方法将路径及相应的处理器注册进ServeMux中。

// HandleFunc registers the handler function for the given pattern.
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
    
    
	if handler == nil {
    
    
		panic("http: nil handler")
	}
	mux.Handle(pattern, HandlerFunc(handler))
}

// Handle registers the handler for the given pattern.
// If a handler already exists for pattern, Handle panics.
func (mux *ServeMux) Handle(pattern string, handler Handler) {
    
    
	mux.mu.Lock()
	defer mux.mu.Unlock()

	if pattern == "" {
    
    
		panic("http: invalid pattern")
	}
	if handler == nil {
    
    
		panic("http: nil handler")
	}
	if _, exist := mux.m[pattern]; exist {
    
    
		panic("http: multiple registrations for " + pattern)
	}

	if mux.m == nil {
    
    
		mux.m = make(map[string]muxEntry)
	}
	e := muxEntry{
    
    h: handler, pattern: pattern}
	mux.m[pattern] = e
	if pattern[len(pattern)-1] == '/' {
    
    
		mux.es = appendSorted(mux.es, e)
	}

	if pattern[0] != '/' {
    
    
		mux.hosts = true
	}
}

同时,ServeMux还实现了Handler接口:
Handler接口仅定义了一个ServeHTTP(ResponseWriter, *Request)方法,用来响应http请求。ServeMux实现了该方法,其主要作用是分发http请求给相应的handler。

// A Handler responds to an HTTP request.
type Handler interface {
    
    
	ServeHTTP(ResponseWriter, *Request)
}

// ServeHTTP dispatches the request to the handler whose
// pattern most closely matches the request URL.
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
    
    
	if r.RequestURI == "*" {
    
    
		if r.ProtoAtLeast(1, 1) {
    
    
			w.Header().Set("Connection", "close")
		}
		w.WriteHeader(StatusBadRequest)
		return
	}
	h, _ := mux.Handler(r)
	h.ServeHTTP(w, r)
}

在上面的代码中,mux.handler(r)会根据请求中的url查找出handler,例如:通过路径/找到helloWorld函数。
而在下一行代码h.ServeHTTP(w, r),函数会调用ServeHTTP方法来处理请求。因为在go中处理请求的统一方法是ServeHTTP(ResponseWriter, *Request),即必须实现handler接口。
其实在上面的注册步骤中,有这样一个语句mux.Handle(pattern, HandlerFunc(handler))。第二个参数HandlerFunc(handler)的作用是将我们写的请求处理函数(例如:helloWord(rw http.ResponseWriter, r *http.Request))强制转换成HandlerFunc类型。HandlerFunc定义如下:

// The HandlerFunc type is an adapter to allow the use of
// ordinary functions as HTTP handlers. If f is a function
// with the appropriate signature, HandlerFunc(f) is a
// Handler that calls f.
type HandlerFunc func(ResponseWriter, *Request)

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

HandlerFunc也实现了ServeHTTP方法,因此也是Handler接口的实现,我们可以看到这个实现本质上是对开发者所写的函数进行封装,以符合golang对于请求处理的规范。
所以,灵活地运用Handler 接口,也可以帮助我们写出一些filter等web中间件。

ListenAndServe

熟悉tcp编程的,其实理解 ListenAndServe过程很容易。其过程大体就是监听指定地址,等待请求,请求进来后解析报文并调用相应的handler。这里不再详细描述。
我们可以注意到,在最开始的示例中,ListenAndServe的第二参数是nil。在这种情况下,当请求进来后就会默认使用DefaultServeMux 。

// ListenAndServe listens on the TCP network address addr and then calls
// Serve with handler to handle requests on incoming connections.
// Accepted connections are configured to enable TCP keep-alives.
//
// The handler is typically nil, in which case the DefaultServeMux is used.
//
// ListenAndServe always returns a non-nil error.
func ListenAndServe(addr string, handler Handler) error {
    
    
	server := &Server{
    
    Addr: addr, Handler: handler}
	return server.ListenAndServe()
}

猜你喜欢

转载自blog.csdn.net/weixin_45804031/article/details/125699733