Go提供了一套完整的Web服务器标准库,使得go构建服务器非常简单,创建服务器只需要调用ListenAndServe即可。相应的Web函数库在net/http包中,本文参考《Go Web编程》中的内容,介绍服务器的构造,有兴趣的小伙伴可以亲自去翻阅这本书。

首先构建两种最简单的服务器:

package main

import (
    "net/http"
)

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

这里直接是用了http包的ListenAndServe函数,用户可以自定义Server对象对服务器进行更多的设置,例如设置超时时间、记录日志等操作。

package main

import (
    "net/http"
)

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

http.Server结构的公开配置如下:

type Server struct {
    Addr           string
    Handler        Handler
    ReadTimeOut    time.Duration
    WriteTimeOut   time.Duration
    MaxHeaderBytes int
    TLSConfig      *tls.Config
    ConnState      func(net.Conn,ConnState)
    ErrorLog       *log.Logger
}

提供HTTPS服务,只需要将监听函数换为server.ListenAndServeTLS("cert.pem", "key.pem")

处理器和处理函数

上面生成的服务器没有写处理程序,无法处理请求,此时需要添加处理器或处理函数。

例如添加处理器:

package main
import (
    "fmt"
    "net/http"
)

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:8080",
        Handler: &handler,
    }
    server.ListenAndServe()
}

如果要使用多个处理器来处理不同的请求:

package main
import (
    "fmt"
    "net/http"
)

type HelloHandler struct{}
func (h *HelloHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello")
}

type WorldHandler struct{}
func (h *WorldHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "World!")
}

func main() {
    hello := HelloHandler{}
    world := WorldHandler{}
    
    server := http.Server{
        Addr: "127.0.0.1:8080",
    }
    http.Handle("/hello", &hello)
    http.Handle("/world", &world)
    
    server.ListenAndServe()
}

这里需要说明的是,在http.Server中不指明handler,则服务器会使用默认的DefaultServeMux处理器,然后使用http.Handle函数将处理器绑定到DefaultServeMux,Handle虽然是http包中的方法,但是它会调用DefaultServeMux.Handle方法。

在上面的定义中,处理器都有一个函数ServeHTTP。在go语言中,一个处理器就是一个拥有ServeHTTP方法的接口。DefaultServeMux多路复用器是ServeMux结构的一个实例,后者也拥有ServeHTTP方法,所以要定义自己的处理器,只需要实现ServeHTTP就行。

上述方式每添加一个请求,就要创建一个handler,会很麻烦。可以使用处理器函数,只需要定义处理函数,而无需创建handler。

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

Go拥有一种handleFunc函数,可以将一个带有(w http.ResponseWriter, r *http.Request)参数的函数转化成handler,跟http.Handle函数一样,都是调用DefaultServeMux的函数。

函数原型为:

func Handle(pattern string, handler Handler) { 
    DefaultServeMux.Handle(pattern, handler) 
}
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
    DefaultServeMux.HandleFunc(pattern, handler)
}