Golang GinWeb框架7-靜態(tài)文件/模板渲染
簡介
本文接著上文(Golang GinWeb框架6-綁定請求字符串/URI/請求頭/復(fù)選框/表單類型)繼續(xù)探索GinWeb框架
靜態(tài)文件服務(wù)
- package main
- import (
- "github.com/gin-gonic/gin"
- "log"
- "net/http"
- "os"
- )
- func main() {
- router := gin.Default()
- cwd, _ := os.Getwd() //獲取當(dāng)前文件目錄
- log.Printf("當(dāng)前項(xiàng)目路徑:%s", cwd)
- router.Static("/static", cwd) //提供靜態(tài)文件服務(wù)器, 第一個(gè)參數(shù)為相對路徑,第二個(gè)參數(shù)為根路徑, 這個(gè)路徑一般放置css,js,fonts等靜態(tài)文件,前端html中采用/static/js/xxx或/static/css/xxx等相對路徑的方式引用
- router.StaticFS("/more_static", http.Dir("./")) //將本地文件樹結(jié)構(gòu)映射到前端, 通過瀏覽器可以訪問本地文件系統(tǒng), 模擬訪問:http://localhost:8080/more_static
- router.StaticFile("/logo.png", "./resources/logo.png") //StaticFile提供單靜態(tài)單文件服務(wù), 模擬訪問:http://localhost:8080/log.png
- // Listen and serve on 0.0.0.0:8080
- router.Run(":8080")
- }
返回文件數(shù)據(jù)
- package main
- import (
- "github.com/gin-contrib/cors"
- "github.com/gin-gonic/gin"
- "net/http"
- )
- func main() {
- router := gin.Default()
- router.Use(cors.Default())
- router.GET("/local/file", func(c *gin.Context) {
- c.File("./main.go")
- })
- // A FileSystem implements access to a collection of named files.
- // The elements in a file path are separated by slash ('/', U+002F)
- // characters, regardless of host operating system convention.
- // FileSystem接口, 要求實(shí)現(xiàn)文件的訪問的方法, 提供文件訪問服務(wù)根路徑的HTTP處理器
- var fs http.FileSystem = http.Dir("./") //將本地目錄作為文件服務(wù)根路徑
- router.GET("/fs/file", func(c *gin.Context) {
- c.FileFromFS("main.go", fs) //將文件服務(wù)系統(tǒng)下的文件數(shù)據(jù)返回
- })
- router.Run(":8080")
- }
- /*
- 模擬訪問文件數(shù)據(jù):
- curl http://localhost:8080/local/file
- 模擬訪問文件系統(tǒng)下的文件數(shù)據(jù):
- curl http://localhost:8080/fs/file
- */
用文件讀出器提供文件數(shù)據(jù)服務(wù)
- package main
- import (
- "github.com/gin-gonic/gin"
- "net/http"
- )
- func main() {
- router := gin.Default()
- router.GET("/someDataFromReader", func(c *gin.Context) {
- response, err := http.Get("https://raw.githubusercontent.com/gin-gonic/logo/master/color.png")
- if err != nil || response.StatusCode != http.StatusOK { //請求鏈接中的文件出現(xiàn)錯(cuò)誤時(shí), 直接返回服務(wù)不可用
- c.Status(http.StatusServiceUnavailable)
- return
- }
- reader := response.Body //用響應(yīng)體內(nèi)容構(gòu)造一個(gè)文件讀出器
- defer reader.Close()
- contentLength := response.ContentLength
- contentType := response.Header.Get("Content-Type")
- extraHeaders := map[string]string{
- "Content-Disposition": `attachment; filename="gopher.png"`,
- }
- // DataFromReader writes the specified reader into the body stream and updates the HTTP code.
- // func (c *Context) DataFromReader(code int, contentLength int64, contentType string, reader io.Reader, extraHeaders map[string]string) {}
- // DataFromReader方法將指定的讀出器reader中的內(nèi)容, 寫入http響應(yīng)體流中, 并更新響應(yīng)碼, 響應(yīng)頭信息等
- c.DataFromReader(http.StatusOK, contentLength, contentType, reader, extraHeaders)
- })
- router.Run(":8080")
- }
- /*
- 模擬訪問:
- curl http://localhost:8080/someDataFromReader
- */
HTML渲染
使用LoadHTMLGlob()方法或LoadHTMLFiles()方法
- package main
- import (
- "github.com/gin-gonic/gin"
- "net/http"
- )
- func main() {
- router := gin.Default()
- //LoadHTMLGlob方法以glob模式加載匹配的HTML文件, 并與HTML渲染器結(jié)合
- router.LoadHTMLGlob("templates/*")
- //router.LoadHTMLFiles("templates/template1.html", "templates/template2.html")
- router.GET("/index", func(c *gin.Context) {
- //HTML方法設(shè)置響應(yīng)碼, 模板文件名, 渲染替換模板中的值, 設(shè)置響應(yīng)內(nèi)容類型Content-Type "text/html"
- c.HTML(http.StatusOK, "index.tmpl", gin.H{
- "title": "Main website",
- })
- })
- router.Run(":8080")
- }
- /*
- 模擬測試:
- curl http://localhost:8080/index
- */
增加模板文件, templates/index.tmpl
- <html>
- <h1>
- {{ .title }}
- </h1>
- </html>
使用不同文件夾下的相同文件名的模板文件
- func main() {
- router := gin.Default()
- router.LoadHTMLGlob("templates/**/*")
- router.GET("/posts/index", func(c *gin.Context) {
- c.HTML(http.StatusOK, "posts/index.tmpl", gin.H{
- "title": "Posts",
- })
- })
- router.GET("/users/index", func(c *gin.Context) {
- c.HTML(http.StatusOK, "users/index.tmpl", gin.H{
- "title": "Users",
- })
- })
- router.Run(":8080")
- }
posts目錄下添加模板文件, templates/posts/index.tmpl
- {{ define "posts/index.tmpl" }}
- <html><h1>
- {{ .title }}
- </h1>
- <p>Using posts/index.tmpl</p>
- </html>
- {{ end }}
users目錄下添加模板文件, templates/users/index.tmpl
- {{ define "users/index.tmpl" }}
- <html><h1>
- {{ .title }}
- </h1>
- <p>Using users/index.tmpl</p>
- </html>
- {{ end }}
自定義模板渲染器
你也可以使用你自定義的HTML模板渲染器, 需要自定義模板文件file1, file2等
- package main
- import (
- "github.com/gin-gonic/gin"
- "html/template"
- "net/http"
- )
- func main() {
- router := gin.Default()
- //template.ParseFiles(文件1,文件2...)創(chuàng)建一個(gè)模板對象, 然后解析一組模板,使用文件名作為模板的名字
- // Must方法將模板和錯(cuò)誤進(jìn)行包裹, 返回模板的內(nèi)存地址 一般用于變量初始化,比如:var t = template.Must(template.New("name").Parse("html"))
- html := template.Must(template.ParseFiles("file1", "file2"))
- router.SetHTMLTemplate(html) //關(guān)聯(lián)模板和HTML渲染器
- router.GET("/index", func(c *gin.Context) {
- //HTML方法設(shè)置響應(yīng)碼, 模板文件名, 渲染替換模板中的值, 設(shè)置響應(yīng)內(nèi)容類型Content-Type "text/html"
- c.HTML(http.StatusOK, "file1", gin.H{
- "title": "Main website",
- })
- })
- router.Run(":8080")
- }
自定義分隔符
你可以自定義分隔符, 模板中默認(rèn)的分隔符是{{ }}, 我們也可以修改, 比如下面增加一對中括號(hào)
- r := gin.Default()
- r.Delims("{[{", "}]}")
- r.LoadHTMLGlob("/path/to/templates")
自定義模板方法
詳見 示例代碼.
模板中與后端都定義好模板方法, 模板渲染時(shí)執(zhí)行該方法, 類似過濾器方法, 比如時(shí)間格式化操作
- package main
- import (
- "fmt"
- "html/template"
- "net/http"
- "time"
- "github.com/gin-gonic/gin"
- )
- func formatAsDate(t time.Time) string {
- year, month, day := t.Date() //Date方法返回年,月,日
- return fmt.Sprintf("%d%02d/%02d", year, month, day) //格式化時(shí)間
- }
- func main() {
- router := gin.Default()
- router.Delims("{[{", "}]}") //自定義模板中的左右分隔符
- //SetFuncMap方法用給定的template.FuncMap設(shè)置到Gin引擎上, 后面模板渲染時(shí)會(huì)調(diào)用同名方法
- //FuncMap是一個(gè)map,鍵名關(guān)聯(lián)方法名, 鍵值關(guān)聯(lián)方法, 每個(gè)方法必須返回一個(gè)值, 或者返回兩個(gè)值,其中第二個(gè)是error類型
- router.SetFuncMap(template.FuncMap{
- "formatAsDate": formatAsDate,
- })
- router.LoadHTMLFiles("./testdata/template/raw.tmpl") //加載單個(gè)模板文件并與HTML渲染器關(guān)聯(lián)
- router.GET("/raw", func(c *gin.Context) {
- c.HTML(http.StatusOK, "raw.tmpl", gin.H{
- "now": time.Date(2017, 07, 01, 0, 0, 0, 0, time.UTC),
- })
- })
- router.Run(":8080")
- }
- /*
- 模擬測試:
- curl http://localhost:8080/raw
- */
定義模板文件: raw.tmpl
- Date: {[{.now | formatAsDate}]}
時(shí)間格式化結(jié)果:
- Date: 2017/07/01
多個(gè)模板
Gin默認(rèn)只使用一個(gè)html.Template模板引擎, 也可以參考多模板渲染器使用類似Go1.6的塊級(jí)模板block template功能.
模板相關(guān)詳情請參考官方template包
參考文檔
Gin官方倉庫:https://github.com/gin-gonic/gin