整合營銷服務(wù)商

          電腦端+手機端+微信端=數(shù)據(jù)同步管理

          免費咨詢熱線:

          Go將HTML字符串渲染為HTML視圖輸出

          做一些文章詳情頁的時候,因為用到了富文本編輯器,因此數(shù)據(jù)庫中存儲的是HTML格式的內(nèi)容,當(dāng)從數(shù)據(jù)庫中讀取顯示到頁面時需要進行轉(zhuǎn)換,否則顯示就是實際的字符串內(nèi)容,因此需要進行轉(zhuǎn)換,轉(zhuǎn)換的代碼很簡單,就是通過關(guān)鍵函數(shù)template.HTML

          示例如下:

          "content":   template.HTML(a.Content),

          另外可以自定義模板函數(shù),在模板文件中使用:

          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包實現(xiàn)了數(shù)據(jù)驅(qū)動的模板,用于生成可對抗代碼注入的安全HTML輸出。它提供了和text/template包相同的接口,Go語言中輸出HTML的場景都應(yīng)使用text/template包。

          模板

          在基于MVC的Web架構(gòu)中,我們通常需要在后端渲染一些數(shù)據(jù)到HTML文件中,從而實現(xiàn)動態(tài)的網(wǎng)頁效果。

          模板示例

          通過將模板應(yīng)用于一個數(shù)據(jù)結(jié)構(gòu)(即該數(shù)據(jù)結(jié)構(gòu)作為模板的參數(shù))來執(zhí)行,來獲得輸出。模板中的注釋引用數(shù)據(jù)接口的元素(一般如結(jié)構(gòu)體的字段或者字典的鍵)來控制執(zhí)行過程和獲取需要呈現(xiàn)的值。模板執(zhí)行時會遍歷結(jié)構(gòu)并將指針表示為’.‘(稱之為”dot”)指向運行過程中數(shù)據(jù)結(jié)構(gòu)的當(dāng)前位置的值。

          用作模板的輸入文本必須是utf-8編碼的文本。”Action”—數(shù)據(jù)運算和控制單位—由”{{“和”}}“界定;在Action之外的所有文本都不做修改的拷貝到輸出中。Action內(nèi)部不能有換行,但注釋可以有換行。

          HTML文件代碼如下:

          我們的HTTP server端代碼如下:

          模板語法

          {{.}}

          模板語法都包含在{{和}}中間,其中{{.}}中的點表示當(dāng)前對象。

          當(dāng)我們傳入一個結(jié)構(gòu)體對象時,我們可以根據(jù).來訪問結(jié)構(gòu)體的對應(yīng)字段。例如:

          HTML文件代碼如下:

          同理,當(dāng)我們傳入的變量是map時,也可以在模板文件中通過.根據(jù)key來取值。

          注釋

          pipeline

          pipeline是指產(chǎn)生數(shù)據(jù)的操作。比如{{.}}、{{.Name}}等。Go的模板語法中支持使用管道符號|鏈接多個命令,用法和unix下的管道類似:|前面的命令會將運算結(jié)果(或返回值)傳遞給后一個命令的最后一個位置。

          注意:并不是只有使用了|才是pipeline。Go的模板語法中,pipeline的概念是傳遞數(shù)據(jù),只要能產(chǎn)生數(shù)據(jù)的,都是pipeline。

          變量

          Action里可以初始化一個變量來捕獲管道的執(zhí)行結(jié)果。初始化語法如下:

          其中$variable是變量的名字。聲明變量的action不會產(chǎn)生任何輸出。

          條件判斷

          Go模板語法中的條件判斷有以下幾種:

          range

          Go的模板語法中使用range關(guān)鍵字進行遍歷,有以下兩種寫法,其中pipeline的值必須是數(shù)組、切片、字典或者通道。

          with

          預(yù)定義函數(shù)

          執(zhí)行模板時,函數(shù)從兩個函數(shù)字典中查找:首先是模板函數(shù)字典,然后是全局函數(shù)字典。一般不在模板內(nèi)定義函數(shù),而是使用Funcs方法添加函數(shù)到模板里。

          預(yù)定義的全局函數(shù)如下:

          比較函數(shù)

          布爾函數(shù)會將任何類型的零值視為假,其余視為真。

          下面是定義為函數(shù)的二元比較運算的集合:

          為了簡化多參數(shù)相等檢測,eq(只有eq)可以接受2個或更多個參數(shù),它會將第一個參數(shù)和其余參數(shù)依次比較,返回下式的結(jié)果:

          {{eq arg1 arg2 arg3}}

          比較函數(shù)只適用于基本類型(或重定義的基本類型,如”type Celsius float32”)。但是,整數(shù)和浮點數(shù)不能互相比較。

          自定義函數(shù)

          Go的模板支持自定義函數(shù)。

          我們可以在模板文件hello.html中使用我們自定義的kua函數(shù)了。

          {{kua .Name}}

          嵌套template

          我們可以在template中嵌套其他的template。這個template可以是單獨的文件,也可以是通過define定義的template。

          舉個例子: t.html文件內(nèi)容如下:

          ul.html文件內(nèi)容如下:

          我們注冊一個templDemo路由處理函數(shù).

          tmplDemo函數(shù)的具體內(nèi)容如下:

          面我們實現(xiàn)了一個最簡單的Web服務(wù)器軟件。這個服務(wù)器軟件很傻,無論你的URL是什么,所有請求都只返回“Hello World!”字符串。而且這個字符串是寫死在代碼中的。

          接下來我們繼續(xù)完善這個Web服務(wù)器軟件,今天我們增加對普通靜態(tài)文件的支持。也就是當(dāng)用戶通過瀏覽器向該服務(wù)器發(fā)送請求的時候該軟件會從磁盤上讀取相應(yīng)的文件,然后發(fā)送給瀏覽器。本次的完善也是很有限的,只對上次的代碼做了很小的改動。這里實現(xiàn)的主要功能是從磁盤讀取一個文件的內(nèi)容,然后封裝http響應(yīng)頭后發(fā)生給瀏覽器。因此,這里主要涉及到Go語言文件訪問相關(guān)的庫的使用。最后實現(xiàn)的效果就是在瀏覽器上顯示html文件渲染后的內(nèi)容:

          圖1 實現(xiàn)效果圖

          文件訪問庫

          由于涉及到文件的訪問,因此這里先介紹一下文件相關(guān)的包。Go語言文件相關(guān)的操作在os包里面,其中os.File封裝了文件讀寫相關(guān)的操作。如下是os包及File涉及的主要函數(shù)和方法,由于篇幅問題,這里只保留的必要的內(nèi)容:

          type File

          File代表一個打開的文件對象。

          func Open(name string) (file *File, err error)

          Open打開一個文件用于讀取。如果操作成功,返回的文件對象的方法可用于讀取數(shù)據(jù);對應(yīng)的文件描述符具有O_RDONLY模式。如果出錯,錯誤底層類型是*PathError。

          func OpenFile(name string, flag int, perm FileMode) (file *File, err error)

          OpenFile是一個更一般性的文件打開函數(shù),大多數(shù)調(diào)用者都應(yīng)用Open或Create代替本函數(shù)。它會使用指定的選項(如O_RDONLY等)、指定的模式(如0666等)打開指定名稱的文件。如果操作成功,返回的文件對象可用于I/O。如果出錯,錯誤底層類型是*PathError。

          func (f *File) Read(b []byte) (n int, err error)

          Read方法從f中讀取最多l(xiāng)en(b)字節(jié)數(shù)據(jù)并寫入b。它返回讀取的字節(jié)數(shù)和可能遇到的任何錯誤。文件終止標(biāo)志是讀取0個字節(jié)且返回值err為io.EOF。

          func (f *File) Write(b []byte) (n int, err error)

          Write向文件中寫入len(b)字節(jié)數(shù)據(jù)。它返回寫入的字節(jié)數(shù)和可能遇到的任何錯誤。如果返回值n!=len(b),本方法會返回一個非nil的錯誤。

          func (f *File) Close() error

          Close關(guān)閉文件f,使文件不能用于讀寫。它返回可能出現(xiàn)的錯誤。

          下面是本文實現(xiàn)的從文件讀取數(shù)據(jù)的方法,在Web服務(wù)的主程序中通過調(diào)用該方法來從磁盤讀取數(shù)據(jù)。這個方法的輸入是文件路徑,輸出是文件的內(nèi)容。

          圖2 文件讀取方法實現(xiàn)


          細(xì)心的同學(xué)可能已經(jīng)發(fā)現(xiàn),我們這里讀取數(shù)據(jù)并沒有用File的Read方法,而是用了另外一個包ioutil的ReadAll方法。這里使用ioutil包的方法也是作為一個引子,期望大家更多的了解Go語言提供的庫函數(shù)。該方法與File的Read方法功能是一樣的,但性能上要好一些。

          ioutil包是一個io相關(guān)的包,提供了對常見io操作的性能優(yōu)化,該包提供的功能主要包括:

          func ReadAll(r io.Reader) ([]byte, error)

          從一個io.Reader讀取所有數(shù)據(jù),并返回一個字節(jié)數(shù)組

          func ReadDir(dirname string) ([]os.FileInfo, error)

          從一個目錄讀取數(shù)據(jù),并得到這個目錄里的文件對象列表

          func ReadFile(filename string) ([]byte, error)

          讀取指定文件的內(nèi)容,并返回一個字節(jié)數(shù)組

          關(guān)于文件操作的相關(guān)介紹本文先到這里,更詳細(xì)的介紹我們后面專門另起新文介紹。

          Web服務(wù)修改

          Web服務(wù)端改動的地方也很少,除了上面介紹的讀取文件內(nèi)容的方法外,在主函數(shù)中調(diào)整了數(shù)據(jù)發(fā)送方面的代碼,其它地方均沒有做改動。下面是涉及到的代碼片段。

          圖3 服務(wù)端代碼修改

          如圖3所示,這里一共修改了3個地方:

          1. 讀取文件(固定的文件),并計算文件的長度
          2. 構(gòu)造http響應(yīng)頭,這里主要是根據(jù)文件大小,調(diào)整Content-Length字段
          3. 分別發(fā)送響應(yīng)頭和響應(yīng)體

          測試驗證

          完成上述修改后,我們就可以通過瀏覽器進行驗證了。這里需要具備一個html文件,該文件保存在與服務(wù)端相同的路徑下面,名稱為index.html。該文件的內(nèi)容如下:

          圖4 HTML文件內(nèi)容

          如果熟悉html的同學(xué),很清楚是做什么的,就是現(xiàn)實一個紅色的“Hello World!”字符串,不了解html的同學(xué)也沒關(guān)系,了解到這里就行。

          在服務(wù)端運行程序, 瀏覽器數(shù)據(jù)地址后回車,可以看到如下內(nèi)容:

          圖5 最終效果圖


          好了,今天先到這,后面文章我們將增加對圖片的支持。

          ?


          主站蜘蛛池模板: 国产精品区AV一区二区| 成人H动漫精品一区二区| 欧美av色香蕉一区二区蜜桃小说 | 福利片福利一区二区三区| 国产丝袜无码一区二区三区视频| 无码少妇丰满熟妇一区二区| 国产精品美女一区二区视频| 国产成人av一区二区三区在线观看| 日本片免费观看一区二区| 日韩精品一区二区三区老鸭窝| 一区二区三区内射美女毛片 | 国产一区二区三区福利| 最新中文字幕一区| 国产在线一区二区视频| 日韩精品一区二区三区影院 | 亚洲片一区二区三区| 亚洲午夜福利AV一区二区无码 | 视频一区二区三区人妻系列| 一区二区三区四区国产| 久久精品综合一区二区三区| 久久无码人妻一区二区三区午夜| 人妻无码视频一区二区三区 | 久久精品国产一区二区| 国产在线精品一区二区在线观看| 精品国产一区AV天美传媒| 精品国产一区二区三区在线| 本免费AV无码专区一区| 日韩人妻无码一区二区三区久久| av无码免费一区二区三区| 在线观看一区二区精品视频| 亚洲一区二区三区在线播放| 日本免费一区二区三区| 国产日韩精品一区二区在线观看 | 日本欧洲视频一区| 成人精品视频一区二区| 国产精品亚洲综合一区在线观看 | 色妞AV永久一区二区国产AV| 成人中文字幕一区二区三区| 熟妇人妻一区二区三区四区| 亚洲一区二区三区播放在线| 国产精品主播一区二区|