Go Echo 学习笔记(九)静态文件&模版文件


静态文件&模版文件

静态文件

一个服务端的 App 中可能会存在很多的像图片、PDF、CSS、JS等静态资源,这些静态资源可以利用 Echo#Static(prefix, root string) 方法来将静态资源的请求路径 prefix 转到项目中存放静态资源的位置 root。

// 请求 /static/js/main.js 将被定位到服务器中的 assets/js/main.js 
e.Static("/static", "assets")

上面这种方式适合访问一个文件夹中的静态文件,但是对于一些单独存放的静态文件,可以使用 Echo#File() 来进行单独指定:

e.File("/logo.png", "./01-demo/img/logo.png")

另外可以用户设置静态文件的方式便是使用 Static 中间件

e.Use(middleware.Static("/static")) // 请求/js/main.js 将被定位到服务器中的 static/js/main.js

模版文件

对于 Go Web 来说,HTML 模版是非常重要的,因为其可以利用模版动作实现向模版中添加指定的数据以及实现模版的设计等功能。

使用模版文件

在 Echo 框架中,可以使用 Context#Render(code int, name string, data interface{}) error 方法(name为模版的名称,data为向模版中填充的数据)来进行模版渲染以及返回功能。只不过在使用该方法之前需要向 Echo 中注册一个对应的模版渲染引擎,Echo 支持任意的渲染引擎。

使用 html/template 作为模版引擎来完成模版内容的显示:

1、实现 echo.Renderer 接口:

type Template struct {
    templates *template.Template
}

func (t *Template) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
    return t.templates.ExecuteTemplate(w, name, data)
}

2、预编译模版:

t := &Template{
    templates: template.Must(template.ParseGlob("public/views/*.html")),
}
// 模版内容public/views/hello.html
Hello, !

3、向 Echo 注册该模版:

e := echo.New()
e.Renderer = t // 注册模版
e.GET("/hello", Hello)

4、在请求处理函数中返回该模版:

func Hello(c echo.Context) error {
    return c.Render(http.StatusOK, "hello", "World")// 向hello模版中填充数据
}

模版文件中调用Echo

Echo#Reverse 方法支持获取到当前的请求路径信息,有时需要在 HTML 界面中打印该信息,这就需要利用模版的功能实现:

1、自定义模版渲染引擎:

// TemplateRenderer 自定义模版渲染器
type TemplateRenderer struct {
	Templates *template.Template
}

// Render 为自定义渲染器实现渲染方法
func (t *TemplateRenderer) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
	// 假如传入的数据是map则添加全局Reverse方法
	if viewContent, isMap := data.(map[string]interface{}); isMap {
		viewContent["reverse"] = c.Echo().Reverse
	}
	// 返回渲染之后的数据
	return t.Templates.ExecuteTemplate(w, name, data)
}

2、预编译模版

renderer := &model.TemplateRenderer{
	Templates: template.Must(template.ParseGlob("./views/pages/*.html")),
}

template.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>Hello </h1>

<p>
   &lt;-- this will call the $x with parameter "foobar"
  
</p>
</body>
</html>

3、向Echo注册该模版

e.Renderer = renderer

4、在请求处理handler中向模版传递数据并返回

func TestTemplate(c echo.Context) error {
	return c.Render(http.StatusOK,"template.html",map[string]interface{}{
		"name":"wangxin",
	})
}
e.GET("/testtemplate", controller.TestTemplate).Name = "foobar"

错误处理

Echo 提倡集中式 HTTP 错误处理,即通过中间件以及请求处理程序来返回错误。集中式的错误处理程序使我们能够从统一的位置将错误记录到外部服务,并向客户端发送自定义的 HTTP 响应。

所返回的错误可以是 error 或者 echo.*HTTPError

对于 echo.*HTTPError 使用 echo.NewHTTPError() 来创建一个包含错误信息的网络请求错误(返回格式为 json):

echo.NewHTTPError(http.StatusUnauthorized, "Please provide valid credentials")

另外也支持使用 e.HTTPErrorHandler 来自定义错误处理程序。

例如可以自定义错误处理程序实现针对不同的错误代码来返回不同的错误页面:

func customHTTPErrorHandler(err error, c echo.Context) {
	code := http.StatusInternalServerError
	if he, ok := err.(*echo.HTTPError); ok {
		code = he.Code
	}
	errorPage := fmt.Sprintf("%d.html", code)
	if err := c.File(errorPage); err != nil {
		c.Logger().Error(err)
	}
	c.Logger().Error(err)
}

e.HTTPErrorHandler = customHTTPErrorHandler