[Golang] 網頁程式設計:製作靜態網頁

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

    前言

    我們先前的範例皆回傳純文字頁面,但實務上我們會回傳 HTML 頁面給使用者觀看,或是回傳 XML (或 JSON) 文件來傳輸資料。本文說明在網頁程式中加入 HTML 頁面的方式。

    (反模式) 直接嵌入網頁

    HTML 文件在本質上是加了標籤 (tag) 的文字文件,所以我們可以直接把整個 HTML 文件當成是一個多行字串輸出。按照這個想法寫出以下 (不良的) 程式碼:

    package main
    
    import (
        "github.com/julienschmidt/httprouter"
        "net/http"
    )
    
    func main() {
        mux := httprouter.New()
        mux.GET("/", index)
    
        server := http.Server{
            Addr: "127.0.0.1:8080",
            Handler: mux,
        }
    
        server.ListenAndServe()
    }
    
    func index(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
        // NEVER DO THIS IN PRODUCTION CODE
        str := `<!DOCTYPE html>
    <html>
    <head><title>Hello, HTML</title></head>
    <body><h1>Hello, HTML</h1><p>Add more text here</p></body>
    </html>
    `
        w.Write([]byte(str))
    }
    

    實務上,我們當然不會這樣做。早期的 CGI 基本上就是用這個思維在寫程式,這套模式已經算是時代的眼淚,我們不需要重覆這樣的舊路線。

    使用模板 (Template)

    在實務上,我們會利用模板 (template) 將內容和版面進行初步的分離。模板是網頁的骨架,會預先寫好一些和板面相關的代碼,要使用模板時再填入原本尚未完成的內容即可。透過模板引擎 (template engine) 的處理,模板和填入的資料會合併後轉為頁面。理論上所有文字格式的內容都能透過這種模式輸出。

    在 Golang 網頁程式中,我們通常拿模板來輸出 HTML 頁面。XML 和 JSON 文件則會用相關函式庫來産生,不會直接用模板去生 XML 或 JSON 文件。

    以本例來說,我們在 views/index.html 加入以下模板:

    <!DOCTYPE html>
    <html>
    <head>
        <title>{{ . }}</title>
    </head>
    <body>
        <p>{{ . }}</p>
    </body>
    </html>
    

    在此模板中,{{ . }} 部分即是挖空的內容,我們可以依需求填入不同的內容。

    接著來看主程式的部分:

    package main
    
    import (
        "github.com/julienschmidt/httprouter"
        "html/template"
        "net/http"
    )
    
    func main() {
        mux := httprouter.New()
        mux.GET("/", index)
    
        server := http.Server{
            Addr: "127.0.0.1:8080",
            Handler: mux,
        }
    
        server.ListenAndServe()
    }
    
    func index(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
        t := template.Must(template.ParseFiles("views/index.html"))
    
        t.Execute(w, "Hello, Template")
    }
    

    本程式的關鍵在於建立和使用模板,我們稍微說明一下。如果想查 API 的使用方式,請查閱 http/template 的文件。

    使用 template.Must 可以建立模板,其函式原型如下:

    func template.Must(tmpl, error) *tmpl
    

    但我們的範例是這樣:

    template.Must(template.ParseFiles("views/index.html"))
    

    如果看範例,會以為我們只傳入一個參數。但實際上我們傳入兩個參數,因為 template.ParseFiles 即會回傳兩個參數,所以可以滿足 template.Must 的 API。會有這樣的現象是因為 template.Must 是設計來搭配其他函式,以簡化建立模板的過程。

    接著來看以 Execute 函式生成模板的函式原型:

    func tmpl.Execute(out, data) err
    

    out 是輸出的目標,在本範例是 http.ResponseWriterdata 利用空介面的特性,可視需求傳入不同的東西。理論上要檢查是否引發錯誤,但本範例為了簡化程式碼,省略這個步驟。

    結語

    在本文中,我們以簡短的範例來展示如何在 Golang 網頁程式中使用模板。在後續的文章中,我們會介紹 Golang 的模板的語法。

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