作为一个真正能用的企业级应用,怎么能缺少RESTful接口呢?所以我们需要尝试在Go语言环境中写出我们的对外接口,这样前端就可以借由Gin框架访问我们数据库中的数据了。
一、Gin框架的使用
1. 安装 Gin
首先,你需要在你的 Go 项目中安装 Gin 框架。可以使用 go get
命令来安装,如果你使用了GoLand作为IDE,直接照着提示引入即可:
bash
go get -u github.com/gin-gonic/gin
2. 创建一个简单的 Gin 应用
go
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
// 创建一个默认的路由引擎
r := gin.Default()
// 定义一个 GET 请求的路由
r.GET("/", func(c *gin.Context) {
c.String(http.StatusOK, "Hello, World!")
})
// 运行服务器,默认监听在 0.0.0.0:8080
r.Run()
}
3. 路由定义
Gin 支持多种 HTTP 方法,如 GET、POST、PUT、DELETE 等。以下是一些基本的路由定义示例:
go
r.GET("/someGet", getting)
r.POST("/somePost", posting)
r.PUT("/somePut", putting)
r.DELETE("/someDelete", deleting)
r.PATCH("/somePatch", patching)
r.HEAD("/someHead", head)
r.OPTIONS("/someOptions", options)
类比于Java,相当于设置了GetMapping、PostMapping。
4. 路由参数
Gin 支持路径参数和查询参数。
路径参数
go
r.GET("/user/:name", func(c *gin.Context) {
name := c.Param("name")
c.String(http.StatusOK, "Hello %s", name)
})
查询参数
go
r.GET("/welcome", func(c *gin.Context) {
firstname := c.DefaultQuery("firstname", "Guest")
lastname := c.Query("lastname") // 等同于 c.Request.URL.Query().Get("lastname")
c.String(http.StatusOK, "Hello %s %s", firstname, lastname)
})
5. 处理表单数据
Gin 可以轻松处理表单数据。
go
r.POST("/form_post", func(c *gin.Context) {
message := c.PostForm("message")
nick := c.DefaultPostForm("nick", "anonymous")
c.JSON(200, gin.H{
"status": "posted",
"message": message,
"nick": nick,
})
})
6. 处理 JSON 数据
Gin 可以轻松处理 JSON 请求和响应。
go
r.POST("/json", func(c *gin.Context) {
var json struct {
Name string `json:"name" binding:"required"`
Age int `json:"age" binding:"required"`
}
if c.BindJSON(&json) == nil {
c.JSON(http.StatusOK, gin.H{
"name": json.Name,
"age": json.Age,
})
} else {
c.JSON(http.StatusBadRequest, gin.H{"error": "请求的JSON有误"})
}
})
7. 中间件
Gin 支持中间件,可以在请求处理之前或之后执行一些操作,放在Java里就相当于AspectJ作为AOP层来实现切面编程。
go
func Logger() gin.HandlerFunc {
return func(c *gin.Context) {
t := time.Now()
// 设置 example 变量
c.Set("example", "12345")
// 请求前
c.Next()
// 请求后
latency := time.Since(t)
log.Print(latency)
// 访问发送的 status
status := c.Writer.Status()
log.Println(status)
}
}
func main() {
r := gin.New()
r.Use(Logger())
r.GET("/test", func(c *gin.Context) {
example := c.MustGet("example").(string)
// 打印:"12345"
log.Println(example)
})
// 监听并在 0.0.0.0:8080 上启动服务
r.Run(":8080")
}
8. 静态文件服务
Gin 可以轻松地提供静态文件服务。
go
r.Static("/assets", "./assets")
r.StaticFS("/more_static", http.Dir("my_file_system"))
r.StaticFile("/favicon.ico", "./resources/favicon.ico")
9. 分组路由
Gin 支持路由分组,可以更好地组织和管理路由。
go
v1 := r.Group("/v1")
{
v1.POST("/login", loginEndpoint)
v1.POST("/submit", submitEndpoint)
v1.POST("/read", readEndpoint)
}
v2 := r.Group("/v2")
{
v2.POST("/login", loginEndpoint)
v2.POST("/submit", submitEndpoint)
v2.POST("/read", readEndpoint)
}
10. 错误处理
Gin 提供了方便的错误处理机制。
go
r.GET("/panic", func(c *gin.Context) {
panic("啊哦,出错了")
})
r.Use(gin.Recovery())
11. 自定义 HTTP 配置
你可以自定义 HTTP 服务器配置。
go
s := &http.Server{
Addr: ":8080",
Handler: r,
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
MaxHeaderBytes: 1 << 20,
}
s.ListenAndServe()
12. 使用模板引擎
Gin 支持模板引擎来渲染 HTML 页面。
go
r.LoadHTMLGlob("templates/*")
r.GET("/index", func(c *gin.Context) {
c.HTML(http.StatusOK, "index.tmpl", gin.H{
"title": "Main website",
})
})
Gin本身没有模板引擎,它用的是Go自带的标准库html/template
和text/template
,下面是一个模板文件的例子:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{ .title }}</title>
</head>
<body>
<h1>{{ .title }}</h1>
<p>欢迎光临我的网站!</p>
</body>
</html>
下面我单独开一章详细介绍一下模板如何编写
13. 使用 Session
Gin 本身不提供 Session 管理,但你可以使用第三方库如 gin-contrib/sessions
。
bash
go get github.com/gin-contrib/sessions
go
import (
"github.com/gin-contrib/sessions"
"github.com/gin-contrib/sessions/cookie"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
store := cookie.NewStore([]byte("secret"))
r.Use(sessions.Sessions("mysession", store))
r.GET("/incr", func(c *gin.Context) {
session := sessions.Default(c)
var count int
v := session.Get("count")
if v == nil {
count = 0
} else {
count = v.(int)
count++
}
session.Set("count", count)
session.Save()
c.JSON(200, gin.H{"count": count})
})
r.Run(":8000")
}
14. 使用 WebSocket
Gin 可以与 WebSocket 结合使用。
go
import (
"github.com/gin-gonic/gin"
"github.com/gorilla/websocket"
"net/http"
)
var upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true
},
}
func websocketHandler(c *gin.Context) {
conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
if err != nil {
return
}
defer conn.Close()
for {
mt, message, err := conn.ReadMessage()
if err != nil {
break
}
err = conn.WriteMessage(mt, message)
if err != nil {
break
}
}
}
func main() {
r := gin.Default()
r.GET("/ws", websocketHandler)
r.Run(":8080")
}
二、模板引擎的使用
刚才我们提到了模板引擎,一般来说对于需要进行SEO优化的网站才会用上模板引擎,而普通的业务系统往往都是前后端分离的,对于前后端分离项目则不需要研究模板引擎如何使用。此外,如果你作为架构师正在考虑生成DSL、生成代码这类操作,也可以使用模板引擎来完成目标。类比于Java而言,模板引擎非常像Freemarker、Velocity这样的框架。Go 语言的 html/template
包是一个功能强大的模板引擎,支持多种模板语法和功能。以下是 html/template
中常用的模板写法:
1. 基本语法
变量输出
使用 {``{ .variable }}
输出变量的值。
html
<p>你好, {{ .Name }}</p>
条件判断
使用 {``{ if .condition }} ... {``{ else }} ... {``{ end }}
进行条件判断。
html
{{ if .IsAdmin }}
<p>管理员</p>
{{ else }}
<p>用户</p>
{{ end }}
循环迭代
使用 {``{ range .list }} ... {``{ end }}
进行循环迭代。
html
<ul>
{{ range .Items }}
<li>{{ . }}</li>
{{ end }}
</ul>
2. 模板继承
定义块
使用 {``{ define "block_name" }} ... {``{ end }}
定义块。
html
{{ define "content" }}
<p>这是一个内容块</p>
{{ end }}
包含块
使用 {``{ template "block_name" . }}
包含块。
html
{{ template "content" . }}
基础模板
使用 {``{ define "base" }} ... {``{ end }}
定义基础模板。
html
{{ define "base" }}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>{{ .Title }}</title>
</head>
<body>
<header>
<h1>{{ .Title }}</h1>
</header>
<main>
{{ template "content" . }}
</main>
<footer>
<p>© 2024 瑜美科技</p>
</footer>
</body>
</html>
{{ end }}
3. 模板函数
内置函数
html/template
提供了一些内置函数,如 and
, or
, not
, len
, index
等。
html
<p>总计数量: {{ len .Items }}</p>
自定义函数
使用 SetFuncMap
注册自定义函数。
go
package main
import (
"html/template"
"net/http"
"time"
)
func formatAsDate(t time.Time) string {
return t.Format("2006-01-02")
}
func main() {
tmpl := template.Must(template.New("").Funcs(template.FuncMap{
"formatAsDate": formatAsDate,
}).ParseFiles("templates/index.tmpl"))
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
tmpl.ExecuteTemplate(w, "index.tmpl", map[string]interface{}{
"Date": time.Now(),
})
})
http.ListenAndServe(":8080", nil)
}
模板文件中使用自定义函数:
html
<p>当前日期为: {{ formatAsDate .Date }}</p>
4. 模板注释
使用 {``{/* ... */}}
添加模板注释。
html
{{/* 这是一段用户用F12也看不到的注释 */}}
<p>您好,{{ .Name }}</p>
5. 模板变量
使用 {``{ $variable := .value }}
定义只在模板渲染生命周期过程中临时产生的变量。
html
{{ $name := .Name }}
<p>您好,{{ $name }}</p>
6. 模板安全
自动转义
html/template
自动转义 HTML 内容,防止 XSS 攻击。
html
<p>{{ .UnsafeHTML }}</p>
不转义
使用 {``{ . | safeHTML }}
不转义 HTML 内容。
html
<p>{{ .UnsafeHTML | safeHTML }}</p>
总结
Gin 是一个功能强大且易于使用的 Web 框架,适用于构建高性能的 Web 应用。html/template
提供了丰富的模板语法和功能,包括变量输出、条件判断、循环迭代、模板继承、模板函数、模板注释、模板操作、模板变量和模板安全等。通过上述示例,你可以快速上手并开始构建你的 Go 语言 Web 应用。至此Go语言24小时极速学习教程就结束了,你可以直接开始参与一些企业级的Go Web项目了。怎么样,学的嗖嗖快对吧,至于数不熟练还需要靠练习,有很多编程中的技巧、数据结构、算法和设计模式与Java基本一致,所以如果你Java和C#玩的很6,相信Go语言也能在1天之内玩的非常6。