1. 程式人生 > 實用技巧 >Go Web伺服器的構造

Go Web伺服器的構造

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)
}