[Golang] 網頁程式設計:撰寫第一個程式

【分享本文】
Facebook Twitter LinkedIn LINE Skype EverNote GMail Yahoo Email

    前言

    在本文中,我們透過極簡的 Hello World 程式來熟悉如何用 Go 撰寫網頁程式。根據網頁是否要加密,程式的寫法略有不同,讀者可相互比較一下。

    一般版的 Hello World

    所謂的一般版是指透過未加密的 HTTP 協定傳輸的網頁程式。透過未加密的 HTTP 協定來傳輸頁面和資料時,不需要做額外的配置,過程較簡單;日後網站要上線時,再將其轉為有加密的 HTTPS 協定即可。

    範例程式碼如下:

    package main
    
    import (
        "fmt"
        "net/http"
    )
    
    func main() {
        // Listen to the root path of the web app
        http.HandleFunc("/", handler)
        
        // Start a web server.
        http.ListenAndServe(":8080", nil)
    }
    
    // The handler for the root path.
    func handler(writer http.ResponseWriter, request *http.Request) {
        fmt.Fprintf(writer, "Hello, World")
    }
    

    在 Go 語言中,撰寫網頁後端程式的主要套件是 net/http。我們會陸續撰寫一些範例,建議讀者搭配該套件的 API 文件來學習,不要直接死記本系列文章中範例的寫法。

    http.HandleFunc 的目的是登記網站路徑的處理器,其函式原型如下:

    http.HandleFunc(path, handler)
    

    以本例 http.HandleFunc("/", handler) 來說,我們在根目錄 / 中登記 handler 這個處理器,網站使用者在向該路徑發出請求 (request) 時,我們的程式即會使用 handler 所實做的內容來回應 (reponse)。在語法上來說,handler 是一個函式,我們這個程式把 handler 當成參數傳入 http 物件中,用到函數式程式的寫法。

    http.ListenAndServe 會啟動一個網頁伺服程式,其函式原型如下:

    http.ListenAndServe(addr, handler)
    

    addr 是用來表示網址的字串,handler 則傳入 ServeMux。所謂的 ServeMux 是 HTTP request multiplexer (mux),mux 統籌處理該網頁程式有登記的路徑及其處理器 (handler),將傳入的路徑指向相對應的處理器,也就是整個網頁程式的路由 (router)。在本例中我們傳入 nil,代表使用內建的 DefaultServeMux

    註:本文的處理器 (handler) 是指處理特定的 HTTP 請求 (request) 的程式碼區塊 (函式或物件),不要和電腦的中央處理器 (CPU) 搞混。

    處理器 (handler) 的寫法如下:

    func handler(w http.ResponseWriter, req *http.Request) {
        // Write something here.
    }
    

    處理器以 *http.Requesthttp.ResponseWriter 為參數,該參數分別代表網頁的請求 (request) 和回應 (response)。以本例來說,我們忽略請求的部分,直接把 "Hello World" 字串輸出到回應。

    使用 Go 主程式執行該程式即可:

    $ go run main.go
    

    (選擇性) 加密版的 Hello World

    在先前的版本中,我們的程式是走未加密的 HTTP 協定,一般情形下是夠用了;必要時,我們仍然可走有加密的 HTTPS 協定。本節說明如何建立走 HTTPS 的 Hello World 程式。

    我們要先安裝 OpenSSL,在類 Unix 系統上使用系統提供的套件即可,若在 Windows 上,可透過 Chocolatey 安裝該套件。利用 OpenSSL 的終端機工具輸入以下指令產生認證和金鑰:

    $ openssl req -newkey rsa:4096 -nodes -sha512 -x509 -days 3650 -nodes -out cert.pem -keyout key.pem
    

    透過此指令,會產生 cert.pem 及 *key.pem*,待會會用到。

    撰寫主程式的部分:

    package main
    
    import (
        "fmt"
        "net/http"
    )
    
    func main() {
        http.HandleFunc("/", handler)
        
        // Start a secure (but not trusted) web server.
        http.ListenAndServeTLS(":8080", "cert.pem", "key.pem", nil)
    }
    
    func handler(writer http.ResponseWriter, request *http.Request) {
        fmt.Fprintf(writer, "Hello, World")
    }
    

    可以看得出來程式碼和先前差不多,主要是啟動時的函式換成 http.ListenAndServeTLS。該函式的原型如下:

    http.ListenAndServeTLS(addr, cert, key, handler)
    

    addr 和先前一樣,填入網址。certkey 分別是認證和金鑰的路徑,按照實際情形填入即可。handler 和先前一樣,是 ServeMux,填入 nil 代表使用預設的 mux。

    使用 https://localhost:8080/ 就可以連到該站台,但使用較新的瀏覽器連線到該站台時,會發現瀏覽器警告我們該站台不安全。這是因為我們的認證和金鑰沒有經過第三方機構公證。由於在早期網站只是要內部使用,直接忽視該警告訊息即可,不用一開始就去進行公證。

    現在有新的工具可以產生受信任的認證和金鑰,有需要的讀者可看下一節。

    (選擇性) 製作受信賴的憑證

    我們上一節談的方法是開發早期需走 HTTPS 時所用的一般性方法,其實應該夠用了。不過,透過 mkcert 這套工具,我們可以不需額外的設定,直接產生受信任的認證和金鑰,簡化開發時程。

    輸入以下指令以產生憑證:

    $ mkcert -install
    

    接著,輸入以下指令以產生適用於 localhost127.0.0.1 的認證和金鑰:

    $ mkcert localhost 127.0.0.1
    Using the local CA at "C:\Users\cwchen\AppData\Local\mkcert" ✨
    
    Created a new certificate valid for the following names 📜
     - "localhost"
     - "127.0.0.1"
    
    The certificate is at "./localhost+1.pem" and the key at "./localhost+1-key.pem" ✅
    

    在啟動伺服器時指定上述檔案即可:

    // Start a secure and trusted web server.
    http.ListenAndServeTLS("localhost:8080", "localhost+1.pem", "localhost+1-key.pem", nil)
    

    連到該站台時,會發現瀏覽器不再吐警告訊息了。

    要注意這個軟體憑證只適用於開發階段,不能用在真正要上線的網頁程式,會有安全上的問題。我們會在發布程式 (deployment) 的章節中,說明如何使用 Let’s Encrypt 來産生可用在實際上線的環境的憑證。

    結語

    雖然這個網頁程式很簡單,但這是了解 Golang 網頁程式的第一步,請讀者還是要實際練習一下。

    在撰寫網頁程式的初期,先用無加密的網頁程式其實無妨;但程式要上線前,最好還是改成加密的版本。現在 HTTPS 可說是網站和網頁程式的標配,不應該再把沒加密的網頁程式直接上線。

    【分享本文】
    Facebook Twitter LinkedIn LINE Skype EverNote GMail Yahoo Email
    【追蹤新文章】
    Facebook Twitter Plurk