Go语言Gin框架学习小计

·  阅读 766

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()
复制代码

返回渲染后的模板(返回包含服务器数据的网页)

  1. 首先要在配置路由前加载模板
r:=gin.Default()
r.LoadHTMLGlob("templates/*")//加载模板代码,此处是指加载templates下面所有一级模板
r.LoadHTMLGlob("templates/**/*")//加载模板代码,此处是指加载templates下面所有一级模板,和子文件夹模板
复制代码
  1. 返回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":"你好",
    })
})
复制代码
  1. 定义模板
<!--给模板定义一个名字 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 -}}
复制代码

比较函数

  1. 布尔函数会将任何类型的零值视为假,其余值视为真。下面是定义为函数的二元比较运算的集合

    运算符解释
    eq如果arg1==arg2则返回真
    ne如果arg1!=arg2则返回真
    lt如果arg1<arg2则返回真
    le如果arg1<=arg2则返回真
    gt如果arg1>arg2则返回真
    ge如果arg1>=arg2则返回真
  2. 例子: 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}}
```
#### 自定义模板函数
  1. 自定义一个函数
//时间戳转换成日期
func UnixToTime(timestamp int) string{
    t:=time.Unix(int64(timestamp),0)
    return t.Format("2006-01-01 03:04:05")
}
复制代码
  1. 把函数注入到框架中 在加载模板的方法(r.LoadHTMLGlob)前面调用r.SetFuncMap把自定义函数注入到map中
r.SetFuncMap(template.FuncMap{
    "UnixToTime":UnixToTime,
}

)
复制代码
  1. 自定义模板函数在模板中的使用
{{ UnixToTime .date }} //其中.date是函数的参数
复制代码

模板嵌套

  1. 创建公共模板在templates文件夹中创建public文件夹,里面放公共模板
  2. 在public文件夹中创建page_head.html
  3. 编辑公共头
{{ define "public/page_header.html" }}
    <style>
        h1{
            background:#ff0000;
            text-align:center;
        }
    </style>
    <h1>我是一个公共的标题</h1>
{{ end }}
复制代码
  1. 外部加载此模板 //注意后面的. 表示把当前页面的数据传递到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

  1. 模板中引入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请求传值

  1. 用户通过普通的请求,获得服务器一个带表单的页面。
router.Get("/user",func(ctx *gin.Context){
    c.HTML(http.StatusOK,"模板",gin.H{})
})
复制代码
  1. 在模板中定义一个form表单

image.png

  1. 在服务器定义路由为/doAddUser的post方法对应客户端的psot请求。

image.png

获取Get Post传递的数据绑定到结构体

  1. 定义结构体

image.png

  1. 把请求数据绑定到结构体 get-post方式相同

image.png

获取客户端post过来的xml数据

  1. 定义结构体

image.png

  1. 把json字符串转成结构体

image.png

  1. 获取post过来的xml数据并转成结构体

image.png

动态路由传值

image.png

路由分组

  1. 前台路由分组

image.png

  1. API接口路由分组

image.png

  1. 后台管理路由分组

image.png

路由文件抽离

文件管理器中 新建routers文件夹,把需要分组的文件放到此文件夹下

  1. 创建AdminRouters.go文件,定义AdminRoutersInit(r *gin.Engine)方法

image.png

  1. main的改变

image.png

控制器文件抽离

  1. 创建相应目录 controllers

    -admin - > 创建 userController.go -api -ielts(前台控制器目录,名字是工程名字即可)

  2. 写对应的方法

image.png

  1. 使用控制器

image.png

控制器继承

  1. 把控制器相关方法绑定到空结构体中

image.png

  1. 在main中使用

image.png

  1. 定义基类控制器

image.png

  1. 继承基类控制器

image.png

继承之后我们就可以在器控制器方法中使用父类定义的控制器方法了。

GIN中间件详解

通俗的讲:中间件是匹配路由前以及匹配路由后完成的一系列操作。Gin框架允许开发者在处理请求的过程中,加入用户自己的钩子函数。这个钩子函数就叫中间件,中间件适合处理一些公共的业务逻辑,比如登录认证,权限校验,数据分页,记录日志,耗时统计等。

定义中间件

  1. 中间件的定义 image.png

其中c.Next()前的代码先于路由调用执行,后的代码路由调用完成之后执行。

  1. 中间件的使用(中间件可以写多个)

image.png

  1. 写多个中间件

image.png

执行顺序, 第一个中间件 输出1->next->第二个中间件输出1->next->路由方法->第二个中间件输出2->第一个中间件输出2

终止执行中间件后面的路由的方法

在中间件写如下方法

c.Abort()
复制代码

全局中间件

全局中间件也可以配置多个

image.png

中间件抽取

根目录创建如下结构 middlewares

- init.go
复制代码

image.png

路由分组中间件

image.png

(中间件-中间件)(中间件控制器之间共享数据)

  1. 中间件中设置值

image.png

  1. 控制器中获取值

image.png

注意事项

  1. 默认中间件问题 image.png
  2. 中间件中使用协程的问题

image.png

gin定义公共模块

新增目录

modules

- tools.go
复制代码

把方法抽取到modules文件夹中的类下面就行了。此处定义的方法在各个地方都可以导入使用。

gin 文件上传

单文件上传和不同文件名多文件上传基本一样

  1. 定义表单

image.png

  1. 定义控制器处理表单提交内容

image.png

同文件名多文件上传

  1. 定义表单 image.png

  2. 定义控制器处理多文件上传 image.png

Gin 设置 cookie

  1. 设置Cookie image.png

  2. 获取Cookie image.png

  3. 删除Cookie

删除Cookie只需要把Cookie过期时间设置为-1即可。或者利用重新设置Cookie的方式把原有Cookie中的值重新覆盖。

  1. Cookie是有域的概念的,在不同的域中cookie不能互相访问。

多个二级域名如何共享Cookie

多个二级域名共享Cookie时,只需要把域名前几位不写即可,比如说:a.baidu.comb.baidu.com我们可以在设置Cookie时写成.baidu.com

Gin 中的Session

image.png

Gin session中间件

image.png

把Session存储到Cookie

image.png

把Session存储到Redis数据库

image.png

待补msyql数据库相关知识点

Gin中使用GORM操作MySql数据库

GORM官方地址GORM官方地址中文版

功能介绍

image.png

1. 连接到数据库

image.png

2. 定义操作数据库表的model

建议定义的model要与数据表名字一样就行。字段建议与数据库字段一致

image.png

2. 查询数据库

image.png

3. 查询数据库带条件(where)

image.png

4. 插入数据

image.png

5. 修改数据

  • 方法1 image.png

  • 方法2 image.png

  • 方法3 image.png

删除数据

  • 方式1 image.png

  • 方式2 image.png

分类:
后端
标签:
收藏成功!
已添加到「」, 点击更改