57. 用模板實現網頁展示(template包)

用 go 實現網站開發,必須學習模板的使用。這樣在網站開發完畢后,如果沒有數據調用或業務邏輯的變化,只是變動界面布局顯示就很輕松了。
首先我們再來實現一下簡單的 web 動態站點

/**
* MyWebserver03
* @Author:  Jian Junbo
* @Email:   junbojian@qq.com
* @Create:  2017/9/27 10:21
* Copyright (c) 2017 Jian Junbo All rights reserved.
*
* Description:  內容展示 web 方式
*/
package main

import (
    "time"
    "net/http"
    "fmt"
)
func main() {
    http.HandleFunc("/", Index)
    http.ListenAndServe(":9090", nil)
}
func Index(w http.ResponseWriter, r *http.Request) {
    fmt.Printf("訪問了地址 %s\n", r.URL.Path)
    fmt.Fprintf(w,"你訪問了地址, %s", r.URL.Path)
}

這個站點實現了在頁面上打印你當前訪問的站點相對地址。


一個常見的功能,點擊一個頁面鏈接,到達一個填寫表單的頁面。填寫完表單,提交給服務器。服務器接收表單信息。
頁面鏈接可以這樣寫

fmt.Fprintf(w, "你可以在<a href='/edit'>這里編輯信息</a>")

我們把它加在 Index 函數中。這樣當訪問根路徑的時候,就可以點擊這個鏈接了。這個鏈接是讓頁面跳轉到 edit 路徑。

func Index(w http.ResponseWriter, r *http.Request) {
    fmt.Printf("%d (%s)訪問了地址 %s\n", time.Now().Unix(), time.Now().Format("2006-01-02 15:04:05.0000000"), r.URL.Path)
    fmt.Fprintf(w,"<div>你訪問了地址, %s</div>", r.URL.Path)
    fmt.Fprintf(w, "你可以在<a href='/edit'>這里編輯信息</a>")
}

由于在 Index 函數中,兩句 Fprintf 的內容是唯一打印在頁面里的。這時候頁面沒有完整的 HTML 編碼。為了避免瀏覽器把這些輸出當作純字符串給輸出出去,我們在第一個 fmt.Fprintf 的內容里也加上了 html 代碼。這只是為了讓瀏覽器識別為頁面。如果正是點做的話,應該寫出完整的頁面結構代碼。
這些代碼運行會顯示成這樣

有鏈接的頁面

完整演示常見功能,我們需要在 main 函數中增加兩個對應的路徑 edit 和 save

    http.HandleFunc("/edit/", editHandler)
    http.HandleFunc("/save/", saveHandler)

對應的也需要完成 editHandler 和 saveHandler 函數,以便訪問對應的路徑有各自相關的功能實現。
editHandler 實現了一個模板頁的渲染,展現為一個表單。同時,預設了一個 Article 類型,并且把相關的數據由模板配合展示在表單下方。

type Article struct {
    Title   string              //標題
    Content string              //內容
    Author  string              //作者
    Tab     []string            //標簽
    PublishTime string          //發表時間
    ViewNum int                 //瀏覽量
}
func editHandler(w http.ResponseWriter, r *http.Request) {
    article := Article{Title:"我的標題", Content:"這是文章的內容", Author:"厚土", Tab:[]string{"練習","實踐"}, PublishTime:time.Now().Format("2006-01-02 15:04:05"), ViewNum:25}
    t, err := template.ParseFiles("tmpl/edit.html")
    if err != nil{
        fmt.Println(err)
        fmt.Fprintf(w, "頁面沒有準備好,請稍后再訪問 ...")
        return
    }
    t.Execute(w, article)
}

這里的模板頁是 edit.html 保存在 tmpl 路徑下。


源碼路徑

如果沒有找到這個模板,就會提示用戶頁面出錯了。

頁面模板出錯提示

在模板頁中,需要顯示數據的地方,都使用 {{}} 來做了標記。{{.}}表示當前的對象,如果要訪問當前對象的字段通過{{.FieldName}},但是需要注意一點:這個字段必須是導出的(字段首字母必須是大寫的),否則在渲染的時候就會報錯。這些標記的數據來源就是 t.Execute(w, article) 里的 article。而 form 標簽中的 action 表示這個表單的數據要提交到 save 路徑,method 方法是確定了提交數據的方式是 post 。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>{{.Title}}</h1>
<form action="/save/" method="post">
    <div>標題<input type="text" name="title"></div>
    <div>作者<input type="text" name="author"></div>
    <div>內容<textarea name="content" rows="20" cols="80"> {{.Content}} </textarea></div>
    <div><input type="submit" value="Save"></div>
</form>
<ul>
    <li>標題:{{.Title}}</li>
    <li>內容:{{.Content}}</li>
    <li>作者:{{.Author}}</li>
    <li>發布時間:{{.PublishTime}}</li>
    <li>標簽:{{range .Tab}}{{.}}、{{end}}</li>
    <li>瀏覽量:{{.ViewNum}}</li>
</ul>
</body>
</html>

在 save 函數中,使用 r.FormValue 接收提交來的數據。

func saveHandler(w http.ResponseWriter, r *http.Request) {
    title := r.FormValue("title")
    author := r.FormValue("author")
    content := r.FormValue("content")

    var article Article
    article.Title = title
    article.Author = author
    article.Content = content
    article.PublishTime = time.Now().Format("2006-01-02 15:04:05.0000000")
    article.Tab = []string{""}
    article.ViewNum = 0

    fmt.Fprintf(w, "我接到了 %s\n", article.Title)
    fmt.Fprintf(w, "標題:%s\n", article.Title)
    fmt.Fprintf(w, "作者:%s\n", article.Author)
    fmt.Fprintf(w, "內容:%s\n", article.Content)
    fmt.Fprintf(w, "發布時間:%s\n", article.PublishTime)
    fmt.Fprintf(w, "標簽:%s\n", article.Tab)
    fmt.Fprintf(w, "瀏覽:%d\n", article.ViewNum)
}

當 save 函數接收到數據后,一般的應用會保存到數據庫中。本程序是把它們都顯示在頁面上了。

表單填寫
接收提交數據
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容