iT邦幫忙

2023 iThome 鐵人賽

DAY 23
0
Modern Web

就是個Go,我也可以啦!GOGO系列 第 23

2023鐵人賽Day 23 Go X web 伺服器

  • 分享至 

  • xImage
  •  

基本的web server處理流程

談談MVC

MVC的概念其實大家都滾瓜爛熟了,但卻也是一個大家跨框架時最好下手認識框架的觀念
MVC由Model(模型)-View(畫面)-Controller(控制器)組成
進入軟體業一年,我想用這樣的方式來解釋MVC

  • 什麼是model: model就是模擬真實世界的東西
    • 只是模擬,像我有一個資料流,我模擬成真實世界存在這樣的東西,我想要讓它界定的更真實一點
    • 因為是一個模擬真實的東西,所以他會有很多屬性,然而記載這些屬性的地方就是model層溝通的資料庫
  • 什麼是controller
    • 他負責接收使用者的請求,並負責給使用者一個回應,這個回應可能是一個畫面,或是一個數據結構
  • 什麼是view
    • view是負責呈現給使用者數據的地方,通常是使用者介面

結論:mvc中model扮演的角色是模擬現實物件,controller負責處理使用者請求,view則負責呈現數據給使用者
這樣子介紹,我希望你們可以把model與controller和view分開,model是一個獨立的個體,因為他是一個獨立模擬出來的物件

再來我們懂MVC後,接下來要談談發送請求到發送請求後怎麼與MVC對接
當使用者發送request後,伺服器端需要有路由器去分配請求路徑該派發到哪一個多工器(controller)處理,在多工器可能會需要與資料庫對接,此時就需要model負責與資料庫溝通,多工器處理完成後可能需要畫面(view)渲染

談談golang的實作

http是一種用於在客戶端和伺服器端之間傳遞數據的協議,我們要理解http構建的過程主要關注兩個端口,client的客戶端及server的伺服器端

客戶端

  1. 客戶端發送請求(request):客戶端向服務器發送http請求。這個請求通常包含以下元素:
    • Headers:包含請求的元資料,例如用戶代理、語言等。
    • HTTP方法:如GET、POST、PUT、DELETE等,表示請求的類型。
    • 目標URL:指定服務器上的資源位置。
    • Body:對於POST或PUT請求,body中可能包含要發送到服務器的數據。

伺服器端

第一步 註冊路由

基本流程是這樣,
我們需要一個ServeMux類型,他是go中的路由分派器->對ServeMux產生實例->並用這個實例執行HandleFunc

  1. ServeMux類型
    • 是什麼? 他在Go的net/http套件中是一個HTTP 請求多路徑器(multiplexer)
    • 主要職責是根據進來的的HTT請求的URL來決定要被哪個處理器(handler)調用
    • ServeMux是一個結構(struct),內部有方法和屬性,其中一個方法就是HandleFunc,他用於將特定的路徑關聯到處理器函數
    type ServeMux struct {
        // ... 其他屬性
    }
    
    func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
        // 這裡是將模式與處理函數關聯起來的具體實作
    }
    
  2. DefaultServeMux
  • net/http 套件提供了一個預設的 ServeMux 實例,稱為 DefaultServeMux
  • 本質上就是一個已經實例化的 ServeMux,供你直接使用
  1. http.HandleFunc 函數
  • 為了簡化流程,Go提供了一個方便的函數稱為http.HandleFunc
  • 這個函數就是直接操作DefaultServeMux,所以也可以說當你呼叫http.HandleFunc時其實就是直接對DefaultServeMuxHandleFunc呼叫
    func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
        DefaultServeMux.HandleFunc(pattern, handler)
    }
    
第二步 開始監聽

我們有了路由處理器後,就要來開始監聽請求,在Go中會使用net/http提供的http.ListenAndServe來監聽請求,那這個function做了什麼事呢,下面我們來分析一下

  • 底層連接處理
    • TCP監聽: 使用net.Listen函數,伺服器開始在指定的地址和端口上監聽TCP連接
    • 接受連接: 伺服器等待和接受來自客戶端的請求
    • 協程處理: 只要接受連接,伺服器端就會啟動一個新的協程來處理http請求和回應,並使用提供的處理器(handler)來生成響應

以上介紹了路由及controller的處理

HandleFunc & Handle

我們來舉兩個簡單的例子

package main

import (
	"fmt"
	"net/http"
)

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

	addr := "localhost:8080"
	fmt.Printf("Starting server on %s...\n", addr)
	err := http.ListenAndServe(addr, nil)
	if err != nil {
		panic(err)
	}
}
package main

import (
	"fmt"
	"net/http"
)

type HelloWorldHandler struct{}

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

func main() {
	handler := &HelloWorldHandler{}
	http.Handle("/", handler)

	addr := "localhost:8080"
	fmt.Printf("Starting server on %s...\n", addr)
	err := http.ListenAndServe(addr, nil)
	if err != nil {
		panic(err)
	}
}

上面兩個例子的差別在於,第二個例子的handler函數是先實現了http.Handler接口的物件,而第一個例子沒有

  • http.Handle

    • 參數:該函數需要兩個參數。第一個是路徑字符串,第二個是實現了http.Handler接口的物件。
    • 當已經有一個物件實現了http.Handler接口(即有一個ServeHTTP方法),可以直接使用此方法將該物件註冊為一個路由的處理程序
  • http.HandleFunc

    • 參數:該函數同樣需要兩個參數。第一個是路徑字符串,第二個是具有特定簽名的函數:func(w http.ResponseWriter, r *http.Request)
    • 當有一個簡單的函數,而不是一個完整的物件實現http.Handler接口,可以使用此方法。實際上,http.HandleFunc在內部創建一個臨時的http.Handler物件來包裝給定的函數
      func handlePage(w http.ResponseWriter, r *http.Request) {
          fmt.Fprint(w, "This is the page handler.")
      }
      http.HandleFunc("/", handlePage)
      
  • 參考連結
    https://www.jianshu.com/p/be3d9cdc680b


上一篇
2023鐵人賽Day 22 Go X html template
下一篇
2023鐵人賽Day 24 Go X 百家爭鳴的router
系列文
就是個Go,我也可以啦!GOGO30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言