您的位置:

全面解析golang http

一、简介

Go语言的net/http包是Go语言内置的一个HTTP处理包,使用该包可以方便地搭建HTTP服务器或者HTTP客户端。本文将从请求处理流程入手,对golang http包进行全面解析。

二、请求处理流程

golang http的请求处理包括:路由、处理函数、中间件等,整个处理流程如下:

    http.ListenAndServe(addr string, handler http.Handler) error

ListenAndServe函数负责创建一个http.Server对象,监听网络端口,并接受来自客户端的请求,并分配给handler处理。handler可以是一个自定义的类型,只要实现了Handler接口。因此,我们可以使用http包默认提供的Mux类型,或者自己实现一个类型来处理请求。

    type HandlerFunc func(w ResponseWriter, r *Request)

HandlerFunc是一个函数类型,用于处理请求的回调函数。函数类型需要满足Handler接口才能作为服务处理函数传给ListenAndServe,具体接口如下:

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

该接口只有一个ServeHTTP方法,负责接收ResponseWriter和Request,其中ResponseWriter为写回客户端的对象,也就是Response,Request则是从客户端发来的请求。一旦接收到请求并将函数转发给ServeHTTP,就会按照golang默认的处理链路:路由 -> 处理函数 -> 中间件 -> 响应返回给客户端。

三、路由

http包提供了一个方便的mux,或多路复用HTTP请求router,称为http.ServeMux。通过使用mux,可以为HTTP服务提供多条处理链路,以便同时处理不同的URI和HTTP方法。下面是一个代码示例

    package main
    import (
        "fmt"
        "net/http"
    )
    func main() {
        http.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
            fmt.Fprintf(w, "Hello")
        })
        http.HandleFunc("/world", func(w http.ResponseWriter, r *http.Request) {
            fmt.Fprintf(w, "World")
        })
        http.ListenAndServe(":8080", nil)
    }

在上面的代码中,使用了`http.HandleFunc()`函数,它接收两个参数:路由地址和一个回调函数来处理该路由。在这个例子中,我们设置了两条路由地址`/hello`和`/world`,并为它们各自设置了一个回调函数。最后,通过调用`http.ListenAndServe()`函数来启动服务,并监听端口`8080`。

四、处理函数

对于每个请求`/hello`和`/world`的回调函数,都需要一个ResponseWriter,由该函数将处理结果返回给客户端。ResponseWriter对象有很多可用的方法,例如Write(), WriteString(), Header() 等。这些方法可以用来向客户端发送数据,设置响应头,或者配置响应状态等。下面是一个处理函数的例子:

    http.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Hello")
    })

在上面的代码中,我们通过`http.HandleFunc()`函数为`/hello`路由地址设置了一个回调函数。这个函数在收到客户端的请求时,将输出`Hello`字符串。

五、中间件

golang http包的中间件是指在进入处理函数之前,对请求和响应进行预处理的插件,包括日志、压缩、请求超时等。中间件可以接受一些参数和可选的行为,比如跳过某些请求、或者直接终止请求处理。中间件函数需要接收一个Handler类型函数并返回一个新的Handler类型函数。以下是一个代码示例:

    func Logger(h http.Handler) http.Handler {
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            start := time.Now()
            h.ServeHTTP(w, r)
            log.Printf("[%s] %s %s", r.Method, r.URL.Path, time.Since(start))
        })
    }
    func Hello(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Hello")
    }
    func main() {
        http.Handle("/hello", Logger(http.HandlerFunc(Hello)))
        http.ListenAndServe(":8080", nil)
    }

在上面的代码中,通过实现中间件Logger函数,我们实现了对服务请求的记录。在正式的处理函数处理完请求之后(h.ServeHTTP(w, r)),记录请求的信息(r.Method, r.URL.Path, time.Since(start))。

六、HTTPS和TLS

HTTPS是HTTP的加密版,采用TLS协议来加密通讯数据。尽管golang不支持对HTTP的TLS,但是它提供了一个轻量级的加密TLS库crypto/tls,可以帮助我们实现HTTPS的功能,如下面的代码所示:

    func main() {
        mux := http.NewServeMux()
        mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
            fmt.Fprintf(w, "Hello, TLS")
        })
        // 生成tls配置
        cert, err := tls.LoadX509KeyPair("server.crt", "server.key")
        if err != nil {
            log.Fatal(err)
        }
        tlsConfig := &tls.Config{Certificates: []tls.Certificate{cert}}
        srv := &http.Server{
            Addr:      ":8443",
            Handler:   mux,
            TLSConfig: tlsConfig,
        }
        log.Fatal(srv.ListenAndServeTLS("", ""))
    }

在上面的代码中,我们创建了一个http.ServeMux对象,并为根URL`/`设置了回调函数。为了启用TLS,我们使用tls.LoadX509KeyPair() 方法加载证书和密钥,它们将用于加密通信。然后,我们将TLS配置传递给http.Server,并将其用作secureconnection。listen 并serve TLS的HTTPS处理链路就这样形成了。

七、总结

本篇文章详细介绍了golang http包的各种使用方法,包括请求处理流程、路由、处理函数、中间件、HTTPS、TLS等方面。通过掌握这些知识点,可以帮助开发人员更好地掌握Http原理,并在实际工作中运用golang http包来搭建Web服务器及开发REST API等。