当前位置:   article > 正文

Go Web开源框架之Gin(1)

Go Web开源框架之Gin(1)

介绍

在今天的技术世界中,我们总是在寻找能够提高开发效率,简化复杂性并提供优秀性能的工具。如果你正在寻找一种轻量级,快速且优雅的Web框架,那么让我介绍一下Gin - 一个Go语言的开源框架,它正是你一直在寻找的那个。

Gin是Go语言中最受欢迎的Web框架之一,它以其超快的速度,极简的API和灵活的路由功能而闻名。无论你是一位熟练的Go开发者,还是刚刚踏入Go的世界,Gin都能为你提供一种简单而有效的方式来构建你的web应用程序。

接下来,我们将一起探索Gin的特点,看看它如何简化Go的Web开发,并提供丰富的功能来优化你的应用。我们还将逐步介绍如何使用Gin来构建一个基本的Web应用程序,这将为你提供一个实际的例子来理解Gin的工作原理。

无论你是对Go语言充满好奇,还是已经使用Go开发并想要探索新的框架,我相信这篇博客都会对你有所帮助。那么,让我们开始吧,一起深入探索Gin的世界。

环境搭建与入门

  1. 下载并安装 gin:
go get -u github.com/gin-gonic/gin
  • 1
  1. 将 gin 引入到代码中:
import "github.com/gin-gonic/gin"
  • 1
  1. 编写 main.go 文件
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")
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  1. 运行项目
go run main.go
  • 1
  1. 改变要运行的端口
r.Run(":9000")
  • 1

Gin 中的路由

路由概述

路由(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")
	})
  • 1
  • 2
  • 3

POST请求:

r.POST("/post", func(c *gin.Context) {
		c.String(200, "post")
	})
  • 1
  • 2
  • 3

PUT请求:

r.PUT("/put", func(c *gin.Context) {
		c.String(200, "put 主要用于更新数据")
	})
  • 1
  • 2
  • 3

DELETE请求:

r.DELETE("/delete", func(c *gin.Context) {
		c.String(200, "delete 主要用于删除数据")
	})
  • 1
  • 2
  • 3

路由中获取值:

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)
	})
  • 1
  • 2
  • 3
  • 4

动态路由:

r.GET("/hello/:name", func(c *gin.Context) {
		name := c.Param("name")
		c.String(200, "hello %s", name)
	})
  • 1
  • 2
  • 3
  • 4

服务端响应类型

返回一个字符串

r.GET("/hi", func(c *gin.Context) {
		c.String(200, "hi world")
	})
  • 1
  • 2
  • 3

返回一个 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,
		})
	})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

返回一个 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"});
	})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

返回 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>
*/
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

渲染模板

// 加载模板
r.LoadHTMLGlob("templates/*")

// 获取POST请求的数据
	r.GET("/login", func(c *gin.Context) {
		c.HTML(200, "templates/index.html", gin.H{})
	})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

HTML模板渲染

模板放置在一个目录下

我们首先在项目根目录新建 templates 文件夹,然后在文件夹中新建 index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
  <h1>{{.title}} </h1>
</body>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

Gin 框架中使用 c.HTML 可以渲染模板,渲染模板前需要使用 LoadHTMLGlob() 或者 LoadHTMLFiles() 方法加载模板。

// 加载模板
r.LoadHTMLGlob("templates/*")

r.GET("/login", func(c *gin.Context) {
		c.HTML(200, "templates/index.html", gin.H{})
	})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

模板在不同目录下

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}}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

文件目录为: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}}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

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",
		})
	})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

注意:如果模板在多级目录里面的话需要这样配置 r.LoadHTMLGlob("templates/** /** /* ")/** 表示目录。

gin模板的基本语法

{{.}}输出数据

模板语法都包含在{{}}中间,其中{{.}}中的点表示当前对象。

当我们传入一个结构体对象时,我们可以根据.来访问结构体的对应字段。

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,
		})
	})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

模板路径: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}}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

注释

注释,执行时会忽略。可以多行。注释不能嵌套,并且必须紧贴分界符始止。

{{/* a comment */}}
  • 1

变量

我们可以在模板中声明变量,用来保存传入模板的数据或其他语句生成的结果。

<h4>{{$obj := .title}}</h4>
<h4> {{$obj}}</h4>
  • 1
  • 2

移除空格

有时候我们在使用模板语法的时候会不可避免的引入一下空格或者换行符,这样模板最终渲 染出来的内容可能就和我们想的不一样,这个时候可以使用 {{-语法去除模板内容左侧的所有 空白符号, 使用-}} 去除模板内容右侧的所有空白符号。

{{- .Name -}}
  • 1

注意:- 要紧挨 {{}} ,同时与模板值之间需要使用空格分隔。

比较函数

布尔函数会将任何类型的零值视为假,其余视为真。

常见的二元比较函数:

函数名解释
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}}
  • 1
  • 2
  • 3

range

Go 的模板语法中使用 range 关键字进行遍历,有以下两种写法,其中 pipeline 的值必须是数组、切片、字典或者通道。

{{range $key, $value := .obj}}
  {{$value}}
{{end}}
  • 1
  • 2
  • 3

如果 pipeline 的值其长度为 0,不会有任何输出。

{$key,$value := .obj}} 
  {{$value}}
{{else}}
  pipeline 的值其长度为 0
{{end}}
  • 1
  • 2
  • 3
  • 4
  • 5

如果 pipeline 的值其长度为 0,则会执行 T0。

main.go

router.GET("/", func(c *gin.Context) {
    c.HTML(http.StatusOK, "default/index.html", map[string]interface{}{
      "hobby": []string{"吃饭", "睡觉", "写代码"}, })
})
  • 1
  • 2
  • 3
  • 4

模板文件:

{{range $key,$value := .hobby}}
  <p>{{$value}}</p> 
{{end}}
  • 1
  • 2
  • 3

With

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,
		})
	})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

之前想要输出数据:

<h4>{{.user.Name}}</h4>
<h4>{{.user.Gender}}</h4>
<h4>{{.user.Age}}</h4>
  • 1
  • 2
  • 3

使用 with 输出数据:

{{with .user}} 
  <h4>姓名:{{.Name}}</h4> 
  <h4>性别:{{.user.Gender}}</h4> 
  <h4>年龄:{{.Age}}</h4>
{{end}}
  • 1
  • 2
  • 3
  • 4
  • 5

简单理解:相当于 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,
	})
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

模板函数路径:ginpro/ginmodel/models

func Print(str1 string, str2 string) {
	fmt.Printf("%s\n", str1+str2)
}
  • 1
  • 2
  • 3

模板访问数据:

{{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}}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

模板嵌套

  1. 新建模板

新建 templates/public/page_header.html

{{define "public/page_header.html"}}

<h1>Hello Header--- {{.title}}</h1>

{{end}}
  • 1
  • 2
  • 3
  • 4
  • 5

新建 templates/public/page_footer.html

{{define "public/page_footer.html"}}

<h1>Hello Footer --- {{.title}}</h1>

{{end}}
  • 1
  • 2
  • 3
  • 4
  • 5
  1. 外部引入

注意:

  • 引入的名字为 page_header.html 中定义的名字
  • 引入的时候注意最后的点(.)
{{/*引入页面头部模板*/}}
{{template "public/page_header.html" .}}
{{/*引入页面底部模板*/}}
{{template "public/page_footer.html" .}}
  • 1
  • 2
  • 3
  • 4

总结

本次主要讲述 Go 开源框架 Gin 的模板使用与路由等。

下期将介绍静态文件,控制器,中间件等。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/974665
推荐阅读
相关标签
  

闽ICP备14008679号