Gin简单的介绍
导包
import "github.com/gin-gonic/gin"
创建路由引擎
func main(){
r:=gin.Default()
}
配置路由
表示:请求第一个参数这个地址的时候,出发后面的回调函数。后面的回调函数有一个gin.Context类型的参数。我们得到这个参数后可以通过这个参数给客户端返回相应的东西
r.GET("/",func(c *gin.Context){
c.String(200,"值:%v","你好gin")
})
启动gin
配置路由完成后我们就可以启动这个gin框架了
r.Run()//启动一个web服务 默认在0.0.0.0:8080端口启动
指定端口号运行
r.Run(:8000)//此处指可以在8000端口上运行此项目
http的几个方法说明
- get 用于向服务器获取数据
- post 用于向服务器提交数据
- put 用于修改服务器数据
- delete 用于删除数据
返回http包里的状态码
http包中给我们定义了好多关于服务器请求的状态码。此时我们可以利用http中的状态码返回给客户端 例如:上面的200我们可以用下面的字面常量来代替
http.StatusOK
返回类型
返回字符串
r.GET("/",func(c *gin.Context){
c.String(200,"值:%v","首页")
})
返回json
//方式 1
r.GET("/json",func(c *gin.Context){
c.Json(200,map[string]interface{}{
"success":true,
"msg":"你好",
})
})
//方式 2
r.GET("/json",func(c *gin.Context){
c.Json(200,gin.H{
"success":true,
"msg":"你好",
})
})
//方式 3 返回结构体
//--定义结构体
type Artile struct{
Title string
Desc string
Content string
}
//--给结构体赋值
a:=&Artile{
Title:"我是一个标题",
Desc:"我是一个描述",
Content:"我是一个内容"
}
//--使用结构体返回
r.GET("/json",a)
})
返回json时利用结构体标签自定义key值
完成此功能需要修改结构体增加结构体标签
type Artile struct{
Title string `json:"title"`
Desc string `json:"desc"`
Content string `json:"content"`
}
返回jsonP
jsonP默认返回的响应数据和json一样,但是如果客户端请求时传入了?callback=xxx,则在返回的时候默认会返回类似xxx({title:"",desc:"",content:""})的值,主要用于解决跨域问题。
c.JSONP()
返回XML数据
返回xml放入的参数和返回json是一样的,可返回结构体和map
c.XML()
返回渲染后的模板(返回包含服务器数据的网页)
- 首先要在配置路由前加载模板
r:=gin.Default()
r.LoadHTMLGlob("templates/*")//加载模板代码,此处是指加载templates下面所有一级模板
r.LoadHTMLGlob("templates/**/*")//加载模板代码,此处是指加载templates下面所有一级模板,和子文件夹模板
- 返回html模板
r.GET("/new",func(c *gin.Context){
c.HTML(200,"news.html",map[string]interface{}{
"title":"我是模板数据",
"msg":"你好",
})
})
r.GET("/new",func(c *gin.Context){
c.HTML(200,"news.html",gin.H{
"title":"我是模板数据",
"msg":"你好",
})
})
- 定义模板
<!--给模板定义一个名字 define end需要成对出现-->
{{ define "default/index.html"}}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{.title}}</title>
</head>
<body>
{{.content}}
</body>
</html>
{{ end }}
在使用此模板时我们要把模板名字写成此处定义的default/index.html
模板数据操作
输出数据
在模板中输出显示后台数据
{{.name}}
在.后面写上后台传过来的key的名字即可
定义变量
1.定义变量t并 用把title里面的数据赋值给他
// 定义变量 并把后台数据赋值给变量
{{ $t := .title}}
2.使用变量
{{$t}}
移除空格
有时候我们在使用模板语法时会不可避免的引入一下空格和换行符,这样模板最终渲染出来的内容可能就和我们想象的不一样。这个时候可以使用{{-
语法去除模板内容左侧的所有空白符号,使用-}}
语法去除模板内容右侧的所有空白符号:
{{- .name -}}
比较函数
-
布尔函数会将任何类型的零值视为假,其余值视为真。下面是定义为函数的二元比较运算的集合 |运算符|解释| |-|-| |eq|如果arg1==arg2则返回真| |ne|如果arg1!=arg2则返回真| |lt|如果arg1<arg2则返回真| |le|如果arg1<=arg2则返回真| |gt|如果arg1>arg2则返回真| |ge|如果arg1>=arg2则返回真|
-
例子: if-else
{{if gt .score 60}}
<p>及格</p>
{{else}}
<p>不及格</p>
{{end}}
if-else-if
{{if gt .score 90}}
<p>及格</p>
{{else if gt .score 80}}
<p>良好</p>
{{else if gt .score 60}}
<p>及格</p>
{{end}}
range
go的模板语法中使用range关键字进行遍历,有以下两种写法,其中pipeline的值必须是数组,切片,字典或通道。
如果pipeline的值其长度为0,不会有任何输出
{{range $key,$value := .obj}}
{{$value}}
{{end}}
如果pipeline的值其长度为0,则输出T0
{{ range $key,$value := .obj}}
{{$value}}
{{else}}
pipeline 的值其长度为0
{{end}}
eg:demo1
<ul>
{range $key,$value := .newsList}
<li>{{$key}} ----- {{$value}}</li>
{{end}}
</ul>
可:嵌套循环
eg:demo2
<ul>
{range $key,$value := .newsList}
<li>{{$key}} ----- {{$value}}</li>
{{else}}
<li>列表中没有数据</li>
{{end}}
</ul>
with 解构
把对象中的属性解构出来,在模板中可以直接使用
用with前
<h4>{{.user.Name}}<h4>
<h4>{{.user.Age}}<h4>
<h4>{{.user.Gender}}<h4>
用with后
{{with .user}}
<h4>姓名:{{.Name}}</h4>
<h4>年龄:{{.Age}}</h4>
<h4>性别:{{.Gender}}</h4>
{{end}}
预定义模板函数
执行模板时函数从两个函数字典中查找:首先是模板函数字典,然后是全局函数字典。一般不在模板内定义函数,而是是用funcs方法添加函数到模板里。
预定义全局函数如下:
函数名 | 解释 |
---|---|
and | ?? |
or | ?? |
not | 返回它的单个参数的布尔值类型的否定 |
len | 返回它参数的整数类型长度 |
index | ?? |
调用预定义函数的列子 |
//利用全局函数。求出.title变量的长度
{{len .title}}
自定义模板函数
- 自定义一个函数
//时间戳转换成日期
func UnixToTime(timestamp int) string{
t:=time.Unix(int64(timestamp),0)
return t.Format("2006-01-01 03:04:05")
}
- 把函数注入到框架中 在加载模板的方法(r.LoadHTMLGlob)前面调用r.SetFuncMap把自定义函数注入到map中
r.SetFuncMap(template.FuncMap{
"UnixToTime":UnixToTime,
}
)
- 自定义模板函数在模板中的使用
{{ UnixToTime .date }} //其中.date是函数的参数
模板嵌套
- 创建公共模板在templates文件夹中创建public文件夹,里面放公共模板
- 在public文件夹中创建page_head.html
- 编辑公共头
{{ define "public/page_header.html" }}
<style>
h1{
background:#ff0000;
text-align:center;
}
</style>
<h1>我是一个公共的标题</h1>
{{ end }}
- 外部加载此模板 //注意后面的. 表示把当前页面的数据传递到page_header里面
{{ template "default/page_header.html" .}}
静态文件服务
当我们渲染的html文件中引用了静态文件时,我们需要配置静态web服务r.Static("/static","./static")前面的/static
表示路由,后面的./static
表示路径
func main(){
r:=gin.Default()
//配置静态web服务,第一个参数表示路由,第二个参数表示 路径
r.Static("/static","./static")
}
创建路径 工程根目录/static/css/base.css
- 模板中引入css
<link rel="stylesheet" href="static/css/base.css">
Get Post 以及获取 Get Post传值
Get请求传值
GET /user?uid=20&page=1
router.Get("/user",func(ctx *gin.Context){
//拿请求中传过来的uid 无默认值
uid:=ctx.Query("uid")
//拿请求中传过来的page 有默认值
page:=ctx.QueryDefault("page","0")
ctx.String(200,"uid = %v page = %v",uid,page)
})
Post请求传值
- 用户通过普通的请求,获得服务器一个带表单的页面。
router.Get("/user",func(ctx *gin.Context){
c.HTML(http.StatusOK,"模板",gin.H{})
})
- 在模板中定义一个form表单
- 在服务器定义路由为
/doAddUser
的post方法对应客户端的psot请求。
获取Get Post传递的数据绑定到结构体
- 定义结构体
- 把请求数据绑定到结构体 get-post方式相同
获取客户端post过来的xml数据
- 定义结构体
- 把json字符串转成结构体
- 获取post过来的xml数据并转成结构体
动态路由传值
路由分组
- 前台路由分组
- API接口路由分组
- 后台管理路由分组
路由文件抽离
文件管理器中 新建routers文件夹,把需要分组的文件放到此文件夹下
- 创建AdminRouters.go文件,定义AdminRoutersInit(r *gin.Engine)方法
- main的改变
控制器文件抽离
-
创建相应目录 controllers
-admin - > 创建 userController.go -api -ielts(前台控制器目录,名字是工程名字即可)
-
写对应的方法
- 使用控制器
控制器继承
- 把控制器相关方法绑定到空结构体中
- 在main中使用
- 定义基类控制器
- 继承基类控制器
继承之后我们就可以在器控制器方法中使用父类定义的控制器方法了。
GIN中间件详解
通俗的讲:中间件是匹配路由前以及匹配路由后完成的一系列操作。Gin框架允许开发者在处理请求的过程中,加入用户自己的钩子函数。这个钩子函数就叫中间件,中间件适合处理一些公共的业务逻辑,比如登录认证,权限校验,数据分页,记录日志,耗时统计等。
定义中间件
- 中间件的定义
其中c.Next()
前的代码先于路由调用执行,后的代码路由调用完成之后执行。
- 中间件的使用(中间件可以写多个)
- 写多个中间件
执行顺序, 第一个中间件 输出1->next->第二个中间件输出1->next->路由方法->第二个中间件输出2->第一个中间件输出2
终止执行中间件后面的路由的方法
在中间件写如下方法
c.Abort()
全局中间件
全局中间件也可以配置多个
中间件抽取
根目录创建如下结构 middlewares
- init.go
路由分组中间件
(中间件-中间件)(中间件控制器之间共享数据)
- 中间件中设置值
- 控制器中获取值
注意事项
- 默认中间件问题
- 中间件中使用协程的问题
gin定义公共模块
新增目录
modules
- tools.go
把方法抽取到modules文件夹中的类下面就行了。此处定义的方法在各个地方都可以导入使用。
gin 文件上传
单文件上传和不同文件名多文件上传基本一样
- 定义表单
- 定义控制器处理表单提交内容
同文件名多文件上传
-
定义表单
-
定义控制器处理多文件上传
Gin 设置 cookie
-
设置Cookie
-
获取Cookie
-
删除Cookie
删除Cookie只需要把Cookie过期时间设置为-1即可。或者利用重新设置Cookie的方式把原有Cookie中的值重新覆盖。
- Cookie是有域的概念的,在不同的域中cookie不能互相访问。
多个二级域名如何共享Cookie
多个二级域名共享Cookie时,只需要把域名前几位不写即可,比如说:a.baidu.com
和b.baidu.com
我们可以在设置Cookie时写成.baidu.com
Gin 中的Session
Gin session中间件
把Session存储到Cookie
把Session存储到Redis数据库
待补msyql数据库相关知识点
Gin中使用GORM操作MySql数据库
功能介绍
1. 连接到数据库
2. 定义操作数据库表的model
建议定义的model要与数据表名字一样就行。字段建议与数据库字段一致
2. 查询数据库
3. 查询数据库带条件(where)
4. 插入数据
5. 修改数据
-
方法1
-
方法2
-
方法3
删除数据
-
方式1
-
方式2