〇、前言
Gin框架是一个用于构建Web应用程序的轻量级Web框架,使用Go语言开发。它具有高性能、低内存占用和快速路由匹配的特点,旨在提供简单、快速的方式来开发可扩展的Web应用程序。
Gin框架的设计目标是保持简单和易于使用,同时提供足够的灵活性和扩展性,使开发人员能够根据项目的需求进行定制。它提供了许多有用的功能,如中间件支持、路由组、请求参数解析、模板渲染等,使开发人员能够快速构建高效的Web应用程序。
以下是Gin框架的一些主要特性:
-
快速的性能:Gin框架采用了高性能的路由引擎,使请求路由匹配变得非常快速。
-
中间件支持:Gin框架支持中间件机制,允许你在请求处理过程中添加自定义的中间件,用于处理认证、日志记录、错误处理等功能。
-
路由组:Gin框架允许将路由按照逻辑组织成路由组,使代码结构更清晰,并且可以为不同的路由组添加不同的中间件。
-
请求参数解析:Gin框架提供了方便的方法来解析请求中的参数,包括查询字符串参数、表单参数、JSON参数等。
-
模板渲染:虽然Gin框架本身不提供模板引擎,但它与多种模板引擎库(如html/template、pongo2等)集成,使你能够方便地进行模板渲染。
-
错误处理:Gin框架提供了内置的错误处理机制,可以捕获和处理应用程序中的错误,并返回适当的错误响应。
总体而言,Gin框架是一个简单、轻量级但功能强大的Web框架,非常适合构建高性能、可扩展的Web应用程序。它在Go语言社区中得到广泛的认可,并被许多开发人员用于构建各种类型的Web应用程序。
一、html/template
html/template
html/template
html/template
(一)初次渲染
hello.tmpl
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<title>Hello</title>
</head>
<body>
<p>hello, {{.}}</p>
</body>
</html>
{{.}}.main.go
package main
import (
"fmt"
"html/template"
"net/http"
)
func sayHello(w http.ResponseWriter, r *http.Request) {
// 请勿刻舟求剑,用绝对地址
t, err := template.ParseFiles("/Users/luliang/GoLand/gin_practice/chap1/hello.tmpl")
if err != nil {
fmt.Println("http server failed:%V", err)
return
}
// 渲染模板
err = t.Execute(w, "小王子!")
if err != nil {
fmt.Println("http server failed:%V", err)
return
}
}
func main() {
http.HandleFunc("/hello", sayHello)
err := http.ListenAndServe(":9000", nil)
if err != nil {
fmt.Println("http server failed:%V", err)
return
}
}
html/template
hello.tmpl
127.0.0.0:9000/hello
(二)传入其它数据进行渲染
err = t.Execute(w, "小王子!")test.tmpl
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<title>Hello</title>
</head>
<body>
<p>姓名: {{.Name}}</p>
<p>年龄: {{.Age}}</p>
<p>性别: {{.Gander}}</p>
</body>
</html>
main.go
package main
import (
"fmt"
"html/template"
"net/http"
)
type User struct {
Name string
Gander string // 首字母是否大小写,作为是否对外暴露的标识
Age int
}
func sayHello(w http.ResponseWriter, r *http.Request) {
// 定义模板
u1 := User{
Name: "小王子",
Gander: "男",
Age: 19,
}
// 解析模板
t, err := template.ParseFiles("/Users/luliang/GoLand/gin_practice/chap2/test.tmpl")
if err != nil {
fmt.Println("ParseFiles failed:%V", err)
return
}
err = t.Execute(w, u1)
if err != nil {
return
}
}
func main() {
http.HandleFunc("/hello", sayHello)
err := http.ListenAndServe(":9000", nil)
if err != nil {
fmt.Println("http server failed:%V", err)
return
}
}
err = t.Execute(w, u1)
type User struct {
Name string
Gander string // 首字母是否大小写,作为是否对外暴露的标识
Age int
}
赶紧看看运行结果,可以看到结果符合预期:
姓名: 小王子
年龄: 19
性别: 男
(三)定义函数参与渲染
f.tmpl
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<title>hello</title>
</head>
<body>
{{ kua . }}
</body>
</html>
kua
main.go
package main
import (
"fmt"
"html/template"
"net/http"
)
func f(w http.ResponseWriter, r *http.Request) {
// 定义模板
k := func(name string) (string, error) {
return name + "太棒了!", nil
}
t := template.New("f.tmpl")
t.Funcs(template.FuncMap{
"kua": k,
})
// 解析模板
_, err := t.ParseFiles("/Users/luliang/GoLand/gin_practice/chap3/f.tmpl")
if err != nil {
return
}
// 渲染模板
err = t.Execute(w, "小王子")
if err != nil {
return
}
}
func main() {
http.HandleFunc("/hello", f)
err := http.ListenAndServe(":9002", nil)
if err != nil {
fmt.Println("http server failed:%V", err)
return
}
}
可以看到,我用了一个关键语句将函数kua 关联到了模板:
t.Funcs(template.FuncMap{
"kua": k,
})
点击运行,可以看到结果:小王子太棒了!
(四)c.HTML() 渲染
在Gin框架中,可以使用c.HTML()方法来进行HTML模板渲染。该方法接收HTTP状态码、模板名称和渲染所需的数据作为参数。
index.tmpl
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>posts/index</title>
</head>
<body>
{{.title}}
</body>
</html>
main.go
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
r := gin.Default()
r.LoadHTMLFiles("/Users/luliang/GoLand/gin_practice/chap4/index.tmpl")
r.GET("/index", func(c *gin.Context) {
c.HTML(http.StatusOK, "index.tmpl", gin.H{
"title": "你好,前端真是太有意思了!",
})
})
r.Run(":9091")
}
首先,创建一个 gin.default()路由对象,然后给该对象载入已经写好的模板文件,之后就可以用 GET 函数进行请求了。
先看看 GET 是什么东西:
// GET is a shortcut for router.Handle("GET", path, handlers).
func (group *RouterGroup) GET(relativePath string, handlers ...HandlerFunc) IRoutes {
return group.handle(http.MethodGet, relativePath, handlers)
}
router.Handle("GET", path, handlers)router.Handle("GET", path, handlers)
func (group *RouterGroup) handle(httpMethod, relativePath string, handlers HandlersChain) IRoutes {
absolutePath := group.calculateAbsolutePath(relativePath)
handlers = group.combineHandlers(handlers)
group.engine.addRoute(httpMethod, absolutePath, handlers)
return group.returnObj()
}
// Handle registers a new request handle and middleware with the given path and method.
// The last handler should be the real handler, the other ones should be middleware that can and should be shared among different routes.
// See the example code in GitHub.
//
// For GET, POST, PUT, PATCH and DELETE requests the respective shortcut
// functions can be used.
//
// This function is intended for bulk loading and to allow the usage of less
// frequently used, non-standardized or custom methods (e.g. for internal
// communication with a proxy).
原来就是做了一下中间处理,注册了一个新的请求句柄。它还说GET, POST, PUT, PATCH、DELETE 都有类似的捷径。之后在 handlers中放一个匿名函数:
func(c *gin.Context) {
c.HTML(http.StatusOK, "index.tmpl", gin.H{
"title": "你好,前端真是太有意思了!",
})
}
c.HTML()
// HTML renders the HTTP template specified by its file name.
// It also updates the HTTP code and sets the Content-Type as "text/html".
// See http://golang.org/doc/articles/wiki/
func (c *Context) HTML(code int, name string, obj any) {
instance := c.engine.HTMLRender.Instance(name, obj)
c.Render(code, instance)
}
Render()
点击运行,结果为:你好,前端真是太有意思了!
(五)从多个模板中选择一个进行渲染
users/index.tmpl
{{define "users/index.tmpl"}}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>users/index</title>
</head>
<body>
{{.title}}
</body>
</html>
{{end}}
posts/index.tmpl
{{define "posts/index.tmpl"}}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>posts/index</title>
</head>
<body>
{{.title}}
</body>
</html>
{{end}}
{{define "posts/index.tmpl"}}...{{end}}main.go
package main
import (
"github.com/gin-gonic/gin"
"html/template"
"net/http"
)
func main() {
r := gin.Default()
r.LoadHTMLGlob("/Users/luliang/GoLand/gin_practice/chap5/templates/**/*")
r.GET("/posts/index", func(c *gin.Context) {
c.HTML(http.StatusOK, "posts/index.tmpl", gin.H{
"title": "posts/index.tmpl",
})
})
r.GET("/users/index", func(c *gin.Context) {
c.HTML(http.StatusOK, "users/index.tmpl", gin.H{
"title": "送你到百度!",
})
})
r.Run(":9091")
}
http://127.0.0.1:9091/users/indexhttp://127.0.0.1:9091/posts/index
(六)加点东西,使得事情朝着有意思的方向进行!
index.css
body {
background-color: #00a7d0;
}
index.js
alert("Hello, Web!")
index.tmpl
{{define "users/index.tmpl"}}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="/xxx/index.css">
<title>users/index</title>
</head>
<body>
{{.title}}
<script src="/xxx/index.js"></script>
</body>
</html>
{{end}}
main.go
package main
import (
"github.com/gin-gonic/gin"
"html/template"
"net/http"
)
func main() {
r := gin.Default()
// 加载静态文件
r.Static("/xxx", "/Users/luliang/GoLand/gin_practice/chap5/statics")
r.LoadHTMLGlob("/Users/luliang/GoLand/gin_practice/chap5/templates/**/*")
r.GET("/posts/index", func(c *gin.Context) {
c.HTML(http.StatusOK, "posts/index.tmpl", gin.H{
"title": "posts/index.tmpl",
})
})
r.GET("/users/index", func(c *gin.Context) {
c.HTML(http.StatusOK, "users/index.tmpl", gin.H{
"title": "送你到百度!",
})
})
r.Run(":9091")
}
r.Static()
可以看到这里出现了一个超链接,那是因为我们在这个字符后面插入了一个函数:
// 添加自定义函数
r.SetFuncMap(template.FuncMap{
"safe": func(str string) template.HTML {
return template.HTML(str)
},
})
index.tmpl
三、利用已有模板进行部署
通过以上的例子,终于学会了在模板中插入大量的css、js 进行渲染了!
首先找到某个网站,比如站长之家,下载一个模板:
选择第一个,下载之后解压:
index.htmlindex.htmlposts
r.GET("/home", func(c *gin.Context) {
c.HTML(http.StatusOK, "index.html", nil)
})
http://127.0.0.1:9091/homemain.go
package main
import (
"github.com/gin-gonic/gin"
"html/template"
"net/http"
)
func main() {
r := gin.Default()
// 加载静态文件
r.Static("/xxx", "/Users/luliang/GoLand/gin_practice/chap5/statics")
// 添加自定义函数
r.SetFuncMap(template.FuncMap{
"safe": func(str string) template.HTML {
return template.HTML(str)
},
})
r.LoadHTMLGlob("/Users/luliang/GoLand/gin_practice/chap5/templates/**/*")
r.GET("/posts/index", func(c *gin.Context) {
c.HTML(http.StatusOK, "posts/index.tmpl", gin.H{
"title": "posts/index.tmpl",
})
})
r.GET("/users/index", func(c *gin.Context) {
c.HTML(http.StatusOK, "users/index.tmpl", gin.H{
"title": "<a href='https://www.baidu.com'>送你到百度!</a>",
})
})
r.GET("/home", func(c *gin.Context) {
c.HTML(http.StatusOK, "index.html", nil)
})
r.Run(":9091")
}
这意味着,我们以后要想写网页,根本不需要进行大量的无意义的编程,利用 ChatGPT,我们可以写出大量的优秀的css、js 网页,我们要做的只是进行适量的改动,这将极大地丰富我们的创造力!
四、总结
本文从简单到难,对Go Web中 gin 框架下的模板渲染进行了简单的阐述。
全文完,感谢阅读!