Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
做一些文章詳情頁的時候,因為用到了富文本編輯器,因此數據庫中存儲的是HTML格式的內容,當從數據庫中讀取顯示到頁面時需要進行轉換,否則顯示就是實際的字符串內容,因此需要進行轉換,轉換的代碼很簡單,就是通過關鍵函數template.HTML
示例如下:
"content": template.HTML(a.Content),
另外可以自定義模板函數,在模板文件中使用:
package main
import (
"html/template"
"github.com/gin-gonic/gin"
)
func main() {
router := gin.Default()
router.SetFuncMap(template.FuncMap{
"safe": func(str string) template.HTML {
return template.HTML(str)
},
})
router.LoadHTMLFiles("./index.tmpl")
router.GET("/index", func(c *gin.Context) {
c.HTML(200, "index.tmpl", "<a href='lizhouwen.com'>1232</a>")
})
router.Run(":9999")
}
html代碼如下:
tml/template包實現了數據驅動的模板,用于生成可對抗代碼注入的安全HTML輸出。它提供了和text/template包相同的接口,Go語言中輸出HTML的場景都應使用text/template包。
在基于MVC的Web架構中,我們通常需要在后端渲染一些數據到HTML文件中,從而實現動態的網頁效果。
模板示例
通過將模板應用于一個數據結構(即該數據結構作為模板的參數)來執行,來獲得輸出。模板中的注釋引用數據接口的元素(一般如結構體的字段或者字典的鍵)來控制執行過程和獲取需要呈現的值。模板執行時會遍歷結構并將指針表示為’.‘(稱之為”dot”)指向運行過程中數據結構的當前位置的值。
用作模板的輸入文本必須是utf-8編碼的文本。”Action”—數據運算和控制單位—由”{{“和”}}“界定;在Action之外的所有文本都不做修改的拷貝到輸出中。Action內部不能有換行,但注釋可以有換行。
HTML文件代碼如下:
我們的HTTP server端代碼如下:
模板語法
{{.}}
模板語法都包含在{{和}}中間,其中{{.}}中的點表示當前對象。
當我們傳入一個結構體對象時,我們可以根據.來訪問結構體的對應字段。例如:
HTML文件代碼如下:
同理,當我們傳入的變量是map時,也可以在模板文件中通過.根據key來取值。
注釋
pipeline
pipeline是指產生數據的操作。比如{{.}}、{{.Name}}等。Go的模板語法中支持使用管道符號|鏈接多個命令,用法和unix下的管道類似:|前面的命令會將運算結果(或返回值)傳遞給后一個命令的最后一個位置。
注意:并不是只有使用了|才是pipeline。Go的模板語法中,pipeline的概念是傳遞數據,只要能產生數據的,都是pipeline。
變量
Action里可以初始化一個變量來捕獲管道的執行結果。初始化語法如下:
其中$variable是變量的名字。聲明變量的action不會產生任何輸出。
條件判斷
Go模板語法中的條件判斷有以下幾種:
range
Go的模板語法中使用range關鍵字進行遍歷,有以下兩種寫法,其中pipeline的值必須是數組、切片、字典或者通道。
with
預定義函數
執行模板時,函數從兩個函數字典中查找:首先是模板函數字典,然后是全局函數字典。一般不在模板內定義函數,而是使用Funcs方法添加函數到模板里。
預定義的全局函數如下:
比較函數
布爾函數會將任何類型的零值視為假,其余視為真。
下面是定義為函數的二元比較運算的集合:
為了簡化多參數相等檢測,eq(只有eq)可以接受2個或更多個參數,它會將第一個參數和其余參數依次比較,返回下式的結果:
{{eq arg1 arg2 arg3}}
比較函數只適用于基本類型(或重定義的基本類型,如”type Celsius float32”)。但是,整數和浮點數不能互相比較。
自定義函數
Go的模板支持自定義函數。
我們可以在模板文件hello.html中使用我們自定義的kua函數了。
{{kua .Name}}
嵌套template
我們可以在template中嵌套其他的template。這個template可以是單獨的文件,也可以是通過define定義的template。
舉個例子: t.html文件內容如下:
ul.html文件內容如下:
我們注冊一個templDemo路由處理函數.
tmplDemo函數的具體內容如下:
面我們實現了一個最簡單的Web服務器軟件。這個服務器軟件很傻,無論你的URL是什么,所有請求都只返回“Hello World!”字符串。而且這個字符串是寫死在代碼中的。
接下來我們繼續完善這個Web服務器軟件,今天我們增加對普通靜態文件的支持。也就是當用戶通過瀏覽器向該服務器發送請求的時候該軟件會從磁盤上讀取相應的文件,然后發送給瀏覽器。本次的完善也是很有限的,只對上次的代碼做了很小的改動。這里實現的主要功能是從磁盤讀取一個文件的內容,然后封裝http響應頭后發生給瀏覽器。因此,這里主要涉及到Go語言文件訪問相關的庫的使用。最后實現的效果就是在瀏覽器上顯示html文件渲染后的內容:
圖1 實現效果圖
由于涉及到文件的訪問,因此這里先介紹一下文件相關的包。Go語言文件相關的操作在os包里面,其中os.File封裝了文件讀寫相關的操作。如下是os包及File涉及的主要函數和方法,由于篇幅問題,這里只保留的必要的內容:
type File
File代表一個打開的文件對象。
func Open(name string) (file *File, err error)
Open打開一個文件用于讀取。如果操作成功,返回的文件對象的方法可用于讀取數據;對應的文件描述符具有O_RDONLY模式。如果出錯,錯誤底層類型是*PathError。
func OpenFile(name string, flag int, perm FileMode) (file *File, err error)
OpenFile是一個更一般性的文件打開函數,大多數調用者都應用Open或Create代替本函數。它會使用指定的選項(如O_RDONLY等)、指定的模式(如0666等)打開指定名稱的文件。如果操作成功,返回的文件對象可用于I/O。如果出錯,錯誤底層類型是*PathError。
func (f *File) Read(b []byte) (n int, err error)
Read方法從f中讀取最多len(b)字節數據并寫入b。它返回讀取的字節數和可能遇到的任何錯誤。文件終止標志是讀取0個字節且返回值err為io.EOF。
func (f *File) Write(b []byte) (n int, err error)
Write向文件中寫入len(b)字節數據。它返回寫入的字節數和可能遇到的任何錯誤。如果返回值n!=len(b),本方法會返回一個非nil的錯誤。
func (f *File) Close() error
Close關閉文件f,使文件不能用于讀寫。它返回可能出現的錯誤。
下面是本文實現的從文件讀取數據的方法,在Web服務的主程序中通過調用該方法來從磁盤讀取數據。這個方法的輸入是文件路徑,輸出是文件的內容。
圖2 文件讀取方法實現
細心的同學可能已經發現,我們這里讀取數據并沒有用File的Read方法,而是用了另外一個包ioutil的ReadAll方法。這里使用ioutil包的方法也是作為一個引子,期望大家更多的了解Go語言提供的庫函數。該方法與File的Read方法功能是一樣的,但性能上要好一些。
ioutil包是一個io相關的包,提供了對常見io操作的性能優化,該包提供的功能主要包括:
func ReadAll(r io.Reader) ([]byte, error)
從一個io.Reader讀取所有數據,并返回一個字節數組
func ReadDir(dirname string) ([]os.FileInfo, error)
從一個目錄讀取數據,并得到這個目錄里的文件對象列表
func ReadFile(filename string) ([]byte, error)
讀取指定文件的內容,并返回一個字節數組
關于文件操作的相關介紹本文先到這里,更詳細的介紹我們后面專門另起新文介紹。
Web服務端改動的地方也很少,除了上面介紹的讀取文件內容的方法外,在主函數中調整了數據發送方面的代碼,其它地方均沒有做改動。下面是涉及到的代碼片段。
圖3 服務端代碼修改
如圖3所示,這里一共修改了3個地方:
測試驗證
完成上述修改后,我們就可以通過瀏覽器進行驗證了。這里需要具備一個html文件,該文件保存在與服務端相同的路徑下面,名稱為index.html。該文件的內容如下:
圖4 HTML文件內容
如果熟悉html的同學,很清楚是做什么的,就是現實一個紅色的“Hello World!”字符串,不了解html的同學也沒關系,了解到這里就行。
在服務端運行程序, 瀏覽器數據地址后回車,可以看到如下內容:
圖5 最終效果圖
好了,今天先到這,后面文章我們將增加對圖片的支持。
?
*請認真填寫需求信息,我們會在24小時內與您取得聯系。