golang轻松渲染JSON、XML和HTML模板响应插件库render的使用

Golang轻松渲染JSON、XML和HTML模板响应插件库Render的使用

Render是一个Go语言包,提供了轻松渲染JSON、XML、文本、二进制数据和HTML模板的功能。

基本用法

Render可以与任何能够访问http.ResponseWriter的Web框架一起使用。渲染函数简单封装了Go现有的数据编组和渲染功能:

  • HTML: 使用html/template包渲染HTML模板
  • JSON: 使用encoding/json包将数据编组为JSON编码的响应
  • XML: 使用encoding/xml包将数据编组为XML编码的响应
  • 二进制数据: 将传入的数据直接传递到http.ResponseWriter
  • 文本: 将传入的字符串直接传递到http.ResponseWriter
// main.go
package main

import (
    "encoding/xml"
    "net/http"

    "github.com/unrolled/render"
)

type ExampleXml struct {
    XMLName xml.Name `xml:"example"`
    One     string   `xml:"one,attr"`
    Two     string   `xml:"two,attr"`
}

func main() {
    r := render.New()
    mux := http.NewServeMux()

    mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
        w.Write([]byte("Welcome, visit sub pages now."))
    })

    mux.HandleFunc("/data", func(w http.ResponseWriter, req *http.Request) {
        r.Data(w, http.StatusOK, []byte("Some binary data here."))
    })

    mux.HandleFunc("/text", func(w http.ResponseWriter, req *http.Request) {
        r.Text(w, JSON、XML和HTML模板响应插件库Render的使用

## 基本用法

Render可以与任何能够访问`http.ResponseWriter`的Web框架一起使用。渲染函数简单封装了Go现有的数据编组和渲染功能:

- **HTML**: 使用`html/template`包渲染HTML模板
- **JSON**: 使用`encoding/json`包将数据编组为JSON编码的响应
- **XML**: 使用`encoding/xml`包将数据编组为XML编码的响应
- **二进制数据**: 将传入的数据直接传递到`http.ResponseWriter`
- **文本**: 将传入的字符串直接传递到`http.ResponseWriter`

```go
// main.go
package main

import (
    "encoding/xml"
    "net/http"

    "github.com/unrolled/render"
)

type ExampleXml struct {
    XMLName xml.Name `xml:"example"`
    One     string   `xml:"one,attr"`
    Two     string   `xml:"two,attr"`
}

func main() {
    r := render.New()
    mux := http.NewServeMux()

    mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
        w.Write([]byte("Welcome, visit sub pages now."))
    })

    mux.HandleFunc("/data", func(w http.ResponseWriter, req *http.Request) {
        r.Data(w, http.StatusOK, []byte("Some binary data here."))
    })

    mux.HandleFunc("/text", func(w http.ResponseWriter, req *http.Request) {
        r.Text(w, http.StatusOK, "Plain text here")
    })

    mux.HandleFunc("/json", func(w http.ResponseWriter, req *http.Request) {
        r.JSON(w, http.StatusOK, map[string]string{"hello": "json"})
    })

    mux.HandleFunc("/jsonp", func(w http.ResponseWriter, req *http.Request) {
        r.JSONP(w, http.StatusOK, "callbackName", map[string]string{"hello": "jsonp"})
    })

    mux.HandleFunc("/xml", func(w http.ResponseWriter, req *http.Request) {
        r.XML(w, http.StatusOK, ExampleXml{One: "hello", Two: "xml"})
    })

    mux.HandleFunc("/html", func(w http.ResponseWriter, req *http.Request) {
        // 假设你在./templates目录下有一个名为"example.tmpl"的模板
        // $ mkdir -p templates && echo "<h1>Hello {{.}}.</h1>" > templates/example.tmpl
        r.HTML(w, http.StatusOK, "example", "World")
    })

    http.ListenAndServe("127.0.0.1:3000", mux)
}
<!-- templates/example.tmpl -->
<h1>Hello {{.}}.</h1>

可用选项

Render提供了多种配置选项:

r := render.New(render.Options{
    Directory: "templates", // 指定加载模板的路径
    FileSystem: &LocalFileSystem{}, // 指定加载文件的文件系统
    Asset: func(name string) ([]byte, error) { // 从Asset函数而不是文件加载
      return []byte("template content"), nil
    },
    AssetNames: func() []string { // 返回Asset函数的资产名称列表
      return []string{"filename.tmpl"}
    },
    Layout: "layout", // 指定布局模板
    Extensions: []string{".tmpl", ".html"}, // 指定要加载的模板扩展名
    Funcs: []template.FuncMap{AppHelpers}, // 指定模板可以访问的辅助函数映射
    Delims: render.Delims{"{[{", "}]}"}, // 设置分隔符为指定字符串
    Charset: "UTF-8", // 设置内容类型的编码
    DisableCharset: true, // 防止字符集附加到内容类型头
    IndentJSON: true, // 输出人类可读的JSON
    IndentXML: true, // 输出人类可读的XML
    PrefixJSON: []byte(")]}',\n"), // 用给定的字节前缀JSON响应
    PrefixXML: []byte("<?xml version='1.0' encoding='UTF-8'?>"), // 用给定的字节前缀XML响应
    HTMLContentType: "application/xhtml+xml", // 输出XHTML内容类型而不是默认的"text/html"
    IsDevelopment: true, // 现在Render将在每个HTML响应上重新编译模板
    UseMutexLock: true, // 覆盖默认的无锁实现并使用标准的`sync.RWMutex`锁
    UnEscapeHTML: true, // 确保'&<>'正确输出(仅限JSON)
    StreamingJSON: true, // 通过json.Encoder流式传输JSON响应
    HTMLTemplateOption: "missingkey=error", // 设置HTML模板的选项值
    RequirePartials: true, // 如果模板缺少布局中使用的部分,则返回错误
    DisableHTTPErrorRendering: true, // 禁用发生错误时自动渲染http.StatusInternalServerError
    JSONEncoder: func(w io.Writer) render.JSONEncoder { // 使用jsoniter "github.com/json-iterator"
        return jsoniter.NewEncoder(w)
    },
})

默认选项

这些是Render的预设选项:

r := render.New()

// 等同于默认配置选项:

r := render.New(render.Options{
    Directory: "templates",
    FileSystem: &LocalFileSystem{},
    Asset: nil,
    AssetNames: nil,
    Layout: "",
    Extensions: []string{".tmpl"},
    Funcs: []template.FuncMap{},
    Delims: render.Delims{"{{", "}}"},
    Charset: "UTF-8",
    DisableCharset: false,
    IndentJSON: false,
    IndentXML: false,
    PrefixJSON: []byte(""),
    PrefixXML: []byte(""),
    BinaryContentType: "application/octet-stream",
    HTMLContentType: "text/html",
    JSONContentType: "application/json",
    JSONPContentType: "application/javascript",
    TextContentType: "text/plain",
    XMLContentType: "application/xhtml+xml",
    IsDevelopment: false,
    UseMutexLock: false,
    UnEscapeHTML: false,
    HTMLTemplateOption: "",
    StreamingJSON: false,
    RequirePartials: false,
    DisableHTTPErrorRendering: false,
    RenderPartialsWithoutPrefix: false,
    BufferPool: GenericBufferPool,
    JSONEncoder: nil,
})

模板加载

默认情况下,Render将尝试从"templates"目录加载扩展名为’.tmpl’的模板。模板是通过遍历模板目录找到的,并按路径和基名命名。例如,以下目录结构:

templates/
  |
  |__ admin/
  |      |
  |      |__ index.tmpl
  |      |
  |      |__ edit.tmpl
  |
  |__ home.tmpl

将提供以下模板:

admin/index
admin/edit
home

布局

Render为布局提供了yieldpartial函数:

r := render.New(render.Options{
    Layout: "layout",
})
<!-- templates/layout.tmpl -->
<html>
  <head>
    <title>My Layout</title>
    <!-- 在这里渲染名为`css-$current_template`的部分模板 -->
    {{ partial "css" }}
  </head>
  <body>
    <!-- 在这里渲染名为`header-$current_template`的部分模板 -->
    {{ partial "header" }}
    <!-- 在这里渲染当前模板 -->
    {{ yield }}
    <!-- 在这里渲染名为`footer-$current_template`的部分模板 -->
    {{ partial "footer" }}
  </body>
</html>

字符编码

Render会根据您调用的函数自动设置适当的Content-Type头。默认情况下,Render会使用UTF-8编码,二进制数据不会输出字符集。

错误处理

渲染函数会返回来自渲染引擎的任何错误。默认情况下,它们还会将错误写入HTTP响应并将状态代码设置为500。您可以通过设置Options.DisableHTTPErrorRendering: true来禁用此行为,以便自己处理错误。

r := render.New(render.Options{
  DisableHTTPErrorRendering: true,
})

err := r.HTML(w, http.StatusOK, "example", "World")
if err != nil{
  http.Redirect(w, r, "/my-custom-500", http.StatusFound)
}

框架集成示例

Echo框架集成

// main.go
package main

import (
    "io"
    "net/http"

    "github.com/labstack/echo"
    "github.com/unrolled/render"
)

type RenderWrapper struct { // 我们需要包装渲染器,因为echo需要不同的签名
    rnd *render.Render
}

func (r *RenderWrapper) Render(w io.Writer, name string, data interface{},c echo.Context) error {
    return r.rnd.HTML(w, 0, name, data) // 零状态码会被echo覆盖
}

func main() {
    r := &RenderWrapper{render.New()}

    e := echo.New()

    e.Renderer = r

    e.GET("/", func(c echo.Context) error {
        return c.Render(http.StatusOK, "TemplateName", "TemplateData")
    })

    e.Logger.Fatal(e.Start("127.0.0.1:8080"))
}

Gin框架集成

// main.go
package main

import (
    "net/http"

    "github.com/gin-gonic/gin"
    "github.com/unrolled/render"
)

func main() {
    r := render.New(render.Options{
        IndentJSON: true,
    })

    router := gin.Default()

    router.GET("/", func(c *gin.Context) {
        r.JSON(c.Writer, http.StatusOK, map[string]string{"welcome": "This is rendered JSON!"})
    })

    router.Run("127.0.0.1:8080")
}

更多关于golang轻松渲染JSON、XML和HTML模板响应插件库render的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang轻松渲染JSON、XML和HTML模板响应插件库render的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Golang渲染JSON、XML和HTML模板的render库使用指南

在Go语言Web开发中,经常需要返回JSON、XML或HTML格式的响应。github.com/unrolled/render是一个简单易用的渲染库,可以帮助我们轻松实现这些功能。

安装render库

go get github.com/unrolled/render

基本使用

初始化render实例

package main

import (
    "net/http"
    
    "github.com/unrolled/render"
)

func main() {
    r := render.New()
    
    http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
        // 渲染逻辑
    })
    
    http.ListenAndServe(":8080", nil)
}

渲染JSON响应

func handlerJSON(w http.ResponseWriter, req *http.Request) {
    data := map[string]interface{}{
        "name":  "John Doe",
        "age":   30,
        "email": "john@example.com",
    }
    
    // 渲染JSON响应
    r.JSON(w, http.StatusOK, data)
    
    // 或者使用结构体
    type User struct {
        Name  string `json:"name"`
        Age   int    `json:"age"`
        Email string `json:"email"`
    }
    
    user := User{
        Name:  "Jane Smith",
        Age:   28,
        Email: "jane@example.com",
    }
    
    r.JSON(w, http.StatusOK, user)
}

渲染XML响应

func handlerXML(w http.ResponseWriter, req *http.Request) {
    type User struct {
        XMLName xml.Name `xml:"user"`
        Name    string   `xml:"name"`
        Age     int      `xml:"age"`
        Email   string   `xml:"email"`
    }
    
    user := User{
        Name:  "Alex Johnson",
        Age:   35,
        Email: "alex@example.com",
    }
    
    // 渲染XML响应
    r.XML(w, http.StatusOK, user)
}

渲染HTML模板

1. 创建模板文件

在项目目录下创建templates文件夹,然后创建hello.html:

<!-- templates/hello.html -->
<!DOCTYPE html>
<html>
<head>
    <title>{{.Title}}</title>
</head>
<body>
    <h1>{{.Title}}</h1>
    <p>Welcome, {{.Name}}!</p>
</body>
</html>

2. 渲染HTML模板

func handlerHTML(w http.ResponseWriter, req *http.Request) {
    // 初始化render时指定模板目录
    r := render.New(render.Options{
        Directory: "templates", // 指定模板目录
        Extensions: []string{".html"}, // 指定模板扩展名
    })
    
    data := map[string]interface{}{
        "Title": "Welcome Page",
        "Name":  "Michael Brown",
    }
    
    // 渲染HTML模板
    r.HTML(w, http.StatusOK, "hello", data)
}

高级配置选项

r := render.New(render.Options{
    Directory:     "templates",       // 模板目录
    Extensions:    []string{".html"}, // 模板扩展名
    Delims:        render.Delims{"{{", "}}"}, // 自定义模板分隔符
    Charset:       "UTF-8",           // 字符编码
    DisableCharset: false,            // 是否禁用字符集
    IndentJSON:    true,              // JSON是否缩进
    IndentXML:     true,              // XML是否缩进
    PrefixJSON:    []byte(")]}',\n"), // JSON前缀
    PrefixXML:     []byte("<?xml version='1.0' encoding='UTF-8'?>"), // XML前缀
})

错误处理

func handlerWithError(w http.ResponseWriter, req *http.Request) {
    if err := someOperation(); err != nil {
        r.JSON(w, http.StatusInternalServerError, map[string]string{
            "error": err.Error(),
        })
        return
    }
    
    // 正常处理
    r.JSON(w, http.StatusOK, map[string]string{"status": "success"})
}

完整示例

package main

import (
    "net/http"
    
    "github.com/unrolled/render"
)

func main() {
    r := render.New(render.Options{
        Directory: "templates",
        Extensions: []string{".html"},
        IndentJSON: true,
    })
    
    http.HandleFunc("/json", func(w http.ResponseWriter, req *http.Request) {
        data := map[string]interface{}{
            "message": "Hello, JSON!",
            "status":  "success",
        }
        r.JSON(w, http.StatusOK, data)
    })
    
    http.HandleFunc("/html", func(w http.ResponseWriter, req *http.Request) {
        data := map[string]interface{}{
            "Title": "Welcome Page",
            "Name":  "Guest User",
        }
        r.HTML(w, http.StatusOK, "hello", data)
    })
    
    http.ListenAndServe(":8080", nil)
}

总结

unrolled/render库提供了简单易用的接口来渲染JSON、XML和HTML响应。它的主要优点包括:

  1. 简洁的API设计
  2. 灵活的配置选项
  3. 内置的模板支持
  4. 自动设置正确的Content-Type头

对于需要返回多种格式响应的Web应用,这个库是一个很好的选择。它减少了样板代码,让开发者可以专注于业务逻辑的实现。

回到顶部