赞
踩
在今天的技术世界中,我们总是在寻找能够提高开发效率,简化复杂性并提供优秀性能的工具。如果你正在寻找一种轻量级,快速且优雅的Web框架,那么让我介绍一下Gin - 一个Go语言的开源框架,它正是你一直在寻找的那个。
Gin是Go语言中最受欢迎的Web框架之一,它以其超快的速度,极简的API和灵活的路由功能而闻名。无论你是一位熟练的Go开发者,还是刚刚踏入Go的世界,Gin都能为你提供一种简单而有效的方式来构建你的web应用程序。
接下来,我们将一起探索Gin的特点,看看它如何简化Go的Web开发,并提供丰富的功能来优化你的应用。我们还将逐步介绍如何使用Gin来构建一个基本的Web应用程序,这将为你提供一个实际的例子来理解Gin的工作原理。
无论你是对Go语言充满好奇,还是已经使用Go开发并想要探索新的框架,我相信这篇博客都会对你有所帮助。那么,让我们开始吧,一起深入探索Gin的世界。
go get -u github.com/gin-gonic/gin
import "github.com/gin-gonic/gin"
package main import ( "github.com/gin-gonic/gin" ) func main() { // 创建一个 gin.Engine r := gin.Default() // 注册路由 r.GET("/hello", func(c *gin.Context) { c.String(200, "hello world") }) // run 默认的服务地址为 127.0.0.1:8080 r.Run("127.0.0.1:8080") }
go run main.go
r.Run(":9000")
路由(Routing)是由一个 URI(或者叫路径)和一个特定的 HTTP 方法(GET、POST 等) 组成的,涉及到应用如何响应客户端对某个网站节点的访问。
RESTful API 是目前比较成熟的一套互联网应用程序的 API 设计理论,所以我们设计我们的路 由的时候建议参考 RESTful API 指南。
在 RESTful 架构中,每个网址代表一种资源,不同的请求方式表示执行不同的操作:
请求方法 | 方法描述 |
---|---|
GET(SELECT) | 从服务器取出资源(一项或多项) |
POST(CREATE) | 在服务器新建一个资源 |
PUT(UPDATE) | 在服务器更新资源(客户端提供改变后的完整资源) |
DELETE(DELETE) | 从服务器删除资源 |
具体的关于RESTful API设计可以观看之前发布的文章:RESTfulAPI 讲解
GET请求:
r.GET("/hello", func(c *gin.Context) {
c.String(200, "hello world")
})
POST请求:
r.POST("/post", func(c *gin.Context) {
c.String(200, "post")
})
PUT请求:
r.PUT("/put", func(c *gin.Context) {
c.String(200, "put 主要用于更新数据")
})
DELETE请求:
r.DELETE("/delete", func(c *gin.Context) {
c.String(200, "delete 主要用于删除数据")
})
路由中获取值:
xxxxxx/test?age="20"
r.GET("/test/:age", func(c *gin.Context) {
age := c.Query("age")
c.String(200, "I am %s years old", age)
})
动态路由:
r.GET("/hello/:name", func(c *gin.Context) {
name := c.Param("name")
c.String(200, "hello %s", name)
})
返回一个字符串
r.GET("/hi", func(c *gin.Context) {
c.String(200, "hi world")
})
返回一个 JSON
数据
// GET /?name=john&age=20&sex=male&address=shanghai
r.GET("/", func(c *gin.Context) {
name := c.Query("name")
age := c.Query("age")
sex := c.Query("sex")
address := c.DefaultQuery("address", "shanghai") //设置默认值为 shanghai
c.JSON(200, gin.H{
"name": name,
"age": age,
"sex": sex,
"address": address,
})
})
返回一个 JSONP
数据
// GET /jsonp?callback=data
r.GET("jsonp", func(c *gin.Context) {
data := gin.H{
"message": "hello world",
}
c.JSONP(200, data)
// 响应格式:data({"message":"hello world"});
})
返回 XML
数据
r.GET("/getXml", func(c *gin.Context) { // 方式一自己拼接xml c.XML(200, gin.H{"name": "john", "age": 20}) }) /* <map> <script/> <name>john</name> <age>20</age> </map> */ r.GET("/getXml2", func(c *gin.Context) { // 方式二使用结构体 type Message struct { Name string Message string Age int } var msg Message msg.Name = "john" msg.Message = "hello world" msg.Age = 20 c.XML(200, msg) }) /* <Message> <script/> <Name>john</Name> <Message>hello world</Message> <Age>20</Age> </Message> */
渲染模板
// 加载模板
r.LoadHTMLGlob("templates/*")
// 获取POST请求的数据
r.GET("/login", func(c *gin.Context) {
c.HTML(200, "templates/index.html", gin.H{})
})
我们首先在项目根目录新建 templates
文件夹,然后在文件夹中新建 index.html
。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>{{.title}} </h1>
</body>
</html>
Gin 框架中使用 c.HTML
可以渲染模板,渲染模板前需要使用 LoadHTMLGlob()
或者 LoadHTMLFiles()
方法加载模板。
// 加载模板
r.LoadHTMLGlob("templates/*")
r.GET("/login", func(c *gin.Context) {
c.HTML(200, "templates/index.html", gin.H{})
})
Gin 框架中如果不同目录下面有同名模板的话我们需要使用下面方法加载模板。
注意:定义模板的时候需要通过 define
定义名称。
文件目录为:templates/admin/index.html
<!-- 相当于给模板定义一个名字 define end 成对出现-->
{{define "admin/index.html"}}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>{{.title}}</h1>
</body>
</html>
{{end}}
文件目录为:templates/default/index.html
{{define "default/index.html"}}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>{{.title}}</h1>
</body>
</html>
{{end}}
main.go 文件
// 加载模板
r.LoadHTMLGlob("templates/**/*")
r.GET("/admin", func(c *gin.Context) {
c.HTML(200, "admin/index.html", gin.H{
"title": "admin index page",
})
})
r.GET("/", func(c *gin.Context) {
c.HTML(200, "default/index.html", gin.H{
"title": "default index page",
})
})
注意:如果模板在多级目录里面的话需要这样配置 r.LoadHTMLGlob("templates/** /** /* ")
, /**
表示目录。
模板语法都包含在{{
和}}
中间,其中{{.}}
中的点表示当前对象。
当我们传入一个结构体对象时,我们可以根据.
来访问结构体的对应字段。
main.go
// 加载模板 r.LoadHTMLGlob("templates/*") r.GET("/news", func(c *gin.Context) { article := Article{ Title: "hello", Content: "hello world", Score: 100, Hobby: []string{"sleep", "eat", "play"}, } articles := []Article{ { Title: "hello1", Content: "hello world", Score: 100, Hobby: []string{"sleep", "eat", "play"}, }, { Title: "hello2", Content: "hello world", Score: 100, Hobby: []string{"sleep", "eat", "play"}, }, { Title: "hello3", Content: "hello world", Score: 100, Hobby: []string{"sleep", "eat", "play"}, }, } c.HTML(200, "default/news.html", gin.H{ "title": "default news page", "news": article, "articles": articles, }) })
模板路径:templates/default/index.html
{{define "default/news.html"}}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="/static/css/base.css">
</head>
<body>
<h1>{{.title}}</h1>
<p>{{.news.Title}}</p>
</body>
</html>
{{end}}
注释,执行时会忽略。可以多行。注释不能嵌套,并且必须紧贴分界符始止。
{{/* a comment */}}
我们可以在模板中声明变量,用来保存传入模板的数据或其他语句生成的结果。
<h4>{{$obj := .title}}</h4>
<h4> {{$obj}}</h4>
有时候我们在使用模板语法的时候会不可避免的引入一下空格或者换行符,这样模板最终渲 染出来的内容可能就和我们想的不一样,这个时候可以使用 {{-语法去除模板内容左侧的所有 空白符号, 使用-}}
去除模板内容右侧的所有空白符号。
{{- .Name -}}
注意:-
要紧挨 {{
和 }}
,同时与模板值之间需要使用空格分隔。
布尔函数会将任何类型的零值视为假,其余视为真。
常见的二元比较函数:
函数名 | 解释 |
---|---|
eq | 如果 arg1 == arg2 则返回真 |
ne | 如果 arg1 != arg2 则返回真 |
lt | 如果 arg1 < arg2 则返回真 |
le | 如果 arg1 <= arg2 则返回真 |
gt | 如果 arg1 > arg2 则返回真 |
ge | 如果 arg1 >= arg2 则返回真 |
Go 模板语法中的条件判断有以下几种:
{{if condition}} T1 {{end}}
{{if condition}} T1 {{else}} T2 {{end}}
{{if condition1}} T1 {{else if condition2}} T2 {{end}}
Go 的模板语法中使用 range
关键字进行遍历,有以下两种写法,其中 pipeline 的值必须是数组、切片、字典或者通道。
{{range $key, $value := .obj}}
{{$value}}
{{end}}
如果 pipeline 的值其长度为 0,不会有任何输出。
{$key,$value := .obj}}
{{$value}}
{{else}}
pipeline 的值其长度为 0
{{end}}
如果 pipeline 的值其长度为 0,则会执行 T0。
main.go
router.GET("/", func(c *gin.Context) {
c.HTML(http.StatusOK, "default/index.html", map[string]interface{}{
"hobby": []string{"吃饭", "睡觉", "写代码"}, })
})
模板文件:
{{range $key,$value := .hobby}}
<p>{{$value}}</p>
{{end}}
main.go
user := struct{
Name string
Gender string
Age int
}{
Name: "john",
Gender: "male",
Age: 20,
}
r.GET("/getuser", func(c *gin.Context) {
c.HTML(200, "templates/index.html", gin.H{
"user": user,
})
})
之前想要输出数据:
<h4>{{.user.Name}}</h4>
<h4>{{.user.Gender}}</h4>
<h4>{{.user.Age}}</h4>
使用 with
输出数据:
{{with .user}}
<h4>姓名:{{.Name}}</h4>
<h4>性别:{{.user.Gender}}</h4>
<h4>年龄:{{.Age}}</h4>
{{end}}
简单理解:相当于 var .=.user
。
main.go
import "ginpro/ginmodel/models"
// 注册模板函数必须在加载模板上面
r.SetFuncMap(template.FuncMap{
"print": models.Print,
})
r.LoadHTMLGlob("templates/*")
r.GET("/hello", func(c *gin.Context) {
c.HTML(200, "ginmodel/deafult.html", gin.H{
"ID": "1",
"message": "Hello World",
"func": models.Print,
})
})
模板函数路径:ginpro/ginmodel/models
func Print(str1 string, str2 string) {
fmt.Printf("%s\n", str1+str2)
}
模板访问数据:
{{define "ginmodel/deafult.html"}}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{{print .ID .message}}
</body>
</html>
{{end}}
新建 templates/public/page_header.html
{{define "public/page_header.html"}}
<h1>Hello Header--- {{.title}}</h1>
{{end}}
新建 templates/public/page_footer.html
{{define "public/page_footer.html"}}
<h1>Hello Footer --- {{.title}}</h1>
{{end}}
注意:
page_header.html
中定义的名字点(.)
{{/*引入页面头部模板*/}}
{{template "public/page_header.html" .}}
{{/*引入页面底部模板*/}}
{{template "public/page_footer.html" .}}
本次主要讲述 Go 开源框架 Gin 的模板使用与路由等。
下期将介绍静态文件,控制器,中间件等。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。