IDE快捷键

1.Ctrl + Shift + /是注释或取消注释选中的多行代码

2.按住Ctrl点变量和函数会有两种跳转

  • 跳转到其定义的地方
  • 跳转到其使用的地方

3.在定义处更改变量或函数名,左边会出现R标识,点击它会对所有旧变量进行Rename

4.函数声明处的左边绿色小圆,点击会跳转到函数实现的地方

5.ctrl+x是剪切

6.shift+”是给选中内容加双引号

7.点击两次鼠标是选中该关键字,点击三次鼠标是选中该行

1.CDN加速,其实是有网络分布式的思想,通过在边缘部署CDN节点,让实际的流量绕开容易拥塞的网络区域

  • CDN的加速资源是跟域名绑定的。
  • 通过域名访问资源,首先是通过DNS分查找离用户最近的CDN节点(边缘服务器)的IP
  • 通过IP访问实际资源时,如果CDN上并没有缓存资源,则会到源站请求资源,并缓存到CDN节点上,这样,用户下一次访问时,该CDN节点就会有对应资源的缓存了。

2.orm是把sql语句封装起来,把对数据库的查询改成面向对象的思想

3.sql注入是指一般sql语句都采用”Select” + name这样常量和变量拼接的形式

  • 当有人在本应输入”num = “+ 2的地方,把2输入成2 or 1=1
  • 那么会输出数据库的所有记录,导致不应被看到的数据暴露出来,这就是标准的sql注入

4.CORS是一个W3C标准,全称是”跨域资源共享”,它允许浏览器向跨源服务器(即使用在某服务器上使用别的服务器的资源),发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制

  • 同源政策是为了防止别的网站对该网站进行攻击,不同源的网站有以下限制
    • Cookie、LocalStorage 和 IndexDB 无法读取
    • DOM 无法获得
    • AJAX 请求不能发送
  • 实现方法是新增了一组HTTP首部字段,允许服务器声明哪些源站通过浏览器有权限访问哪些资源
  • 对那些可能对服务器数据产生副作用的HTTP请求方法(特别是GET以外的HTTP请求),浏览器必须首先使用OPTIONS方法发起一个预检请求,从而获知服务端是否允许该跨源请求。服务器确认允许之后,才发起实际的HTTP请求
  • Origin首部字段表明预检请求或实际请求的源站
  • Access-Control-Allow-Origin参数的值指定了允许访问该资源的外域url,对于不需要携带身份凭证的请求,服务器可以指定该字段的值为通配符*,表示允许来自所有域的请求
    1
    2
    3
    //表示允许来自https://mozilla.org的请求
    Access-Control-Allow-Origin: https://mozilla.org
    Vary: Origin
  • Access-Control-Allow-Methods首部字段用于预检请求的响应。其指明了实际请求所允许使用的 HTTP 方法
  • Access-Control-Allow-Headers首部字段用于预检请求的响应。其指明了实际请求中允许携带的首部字段
  • Access-Control-Expose-Headers把允许浏览器访问的头放入白名单
  • Access-Control-Allow-Credentials头指定了当浏览器的credentials设置为true时是否允许浏览器读取response的内容
  • 一般写在中间件里面
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    func CORS() gin.HandlerFunc {
    return func(c *gin.Context) {
    method := c.Request.Method
    origin := c.Request.Header.Get("Origin")
    if origin != "" {
    //c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
    c.Header("Access-Control-Allow-Origin", "*") // 可将 * 替换为指定的域名
    c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE")
    c.Header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization")
    c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Cache-Control, Content-Language, Content-Type")
    c.Header("Access-Control-Allow-Credentials", "true")
    }
    if method == "OPTIONS" {
    c.AbortWithStatus(http.StatusNoContent)
    }
    c.Next()
    }
    }

5.RPC框架

  • 为什么需要RPC:RPC是指远程过程调用,也就是说两台服务器A,B,一个应用部署在A服务器上,想要调用B服务器上应用提供的函数/方法,由于不在—个内存空间,不能直接调用,需要通过网络来表达调用的语义和传达调用的数据

6.数据库软删除和硬删除,可以在大多时候提高效率

  • 硬删除:直接从表里去除该条记录
  • 软删除:用一个del字段表示是否被删除

7.putty用于远程连接云服务器

8.origin是远程仓库的默认别名

9.测试问题

  • 数据库数据的耦合性高,导致某些功能的测试依赖现实数据
  • 前后端字段不一致易导致问题

10.MD5加密(通常用来将密码加密后存数据库):MD5消息摘要算法,属Hash算法一类。MD5算法对输入任意长度的消息进行运行,产生一个128位的消息摘要

  • 数据填充
    • 对消息进行数据填充,使消息的长度对512取模得448,设消息长度为X,即满足X mod 512=448。根据此公式得出需要填充的数据长度。
    • 填充方法:在消息后面进行填充,填充第一位为1,其余为0。
  • 添加消息长度
    -在第一步结果之后再填充上原消息的长度,可用来进行的存储长度为64位。如果消息长度大于264,则只使用其低64位的值,即(消息长度 对 264取模)。
    • 在此步骤进行完毕后,最终消息长度就是512的整数倍。
  • 数据处理
    • 准备需要用到的数据:
      • 4个常数: A = 0x67452301, B = 0x0EFCDAB89, C = 0x98BADCFE, D = 0x10325476;
      • 4个函数:F(X,Y,Z)=(X & Y) | ((X) & Z); G(X,Y,Z)=(X & Z) | (Y & (Z)); H(X,Y,Z)=X ^ Y ^ Z; I(X,Y,Z)=Y ^ (X | (~Z));
    • 把消息分以512位为一分组进行处理,每一个分组进行4轮变换,以上面所说4个常数为起始变量进行计算,重新输出4个变量,以这4个变量再进行下一分组的运算,如果已经是最后一个分组,则这4个变量为最后的结果,即MD5值

10.面向过程和面向对象

  • 面向过程是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了
  • 面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为

11.nginx的作用

12.LF和CRLF的区别

  • LF是\n换行,是linux系统的换行方式
  • CRLF是\r\n回车换行,是windows系统的换行方式
  • 两者实际并无区别,只是windows下写的文件(markdown等)直接放到linux上使用会自动将所有CRLF替换成LF

13.CI/CD是指持续集成、持续交付、持续部署

  • 持续集成(CI):将各个开发人员的工作集合到一个代码仓库中。通常,每天都要进行几次,主要目的是尽早发现集成错误,使团队更好地协作
  • 持续交付(CD):最小化部署或释放过程中固有的摩擦。它的实现通常能够将构建部署的每个步骤自动化,以便任何时刻能够安全地完成代码发布(理想情况下)
  • 持续部署(CD):无论何时对代码进行重大更改,都会自动进行构建/部署

14.80端口是http协议的端口,也是Web默认访问的端口,如果想要外界能够访问你的服务器的话,一定要开放你的80端口,如果80端口被封就相当于网站被封

15.Nginx的作用

  • 静态HTTP服务器:将服务器上的静态文件(如HTML、图片)通过HTTP协议展现给客户端访问
  • 反向代理服务器:客户端本来可以直接通过HTTP协议访问某网站应用服务器,网站管理员可以在中间加上一个Nginx,客户端请求Nginx,Nginx请求应用服务器,然后将结果返回给客户端,此时Nginx就是反向代理服务器,目的是通过Nginx实现负载均衡
  • 负载均衡:将同一个网站部署在多台服务器上,将大量用户的请求分配给多台机器处理
  • 虚拟主机:将多个网站部署在同一台服务器上,即一个端口一个网站,但是其实都还是同一台机器处理的用户请求

16.Gitlab的CI/CD会把服务器的带宽跑满,所以此时服务器上的项目接口无法调用

17.浏览器在处理跨域访问的请求时如果判断请求为复杂请求,则会先向服务器发送一条预检请求(这就是为什么第一次请求接口是204),根据服务器返回的内容浏览器判断服务器是否允许该请求访问。

  • 如果web服务器采用cors的方式支持跨域访问,在处理复杂请求时这个预检请求是不可避免的
  • 且该状态为204的请求的Request Method是OPTIONS,OPTIONS就代表了预检请求

18.unicode编码是3个字节表示所有世界字符的形式,UTF-8是一种变长的Unicode改进编码方式,即英文用1个字节,运算符号用2个字节,中文用3字节表示

1.小程序项目中单个页面会依赖不同类型的文件

  • .json 后缀的 JSON 配置文件
  • .ttml 后缀的 TTML 模板文件
  • .ttss 后缀的 TTSS 样式文件
  • .js 后缀的 JS 脚本文件

2.小程序的目录结构

1
2
3
4
5
6
7
8
9
10
11
.
├── app.js //小程序逻辑
├── app.json //小程序公共配置
├── app.ttss //小程序公共样式表
├── project.config.json //项目配置
└── pages
└── pageA
├── pageA.ttss
├── pageA.js
├── pageA.json
└── pageA.ttml

3.一个简体流程就是

  • 根目录
    • app.js和app.ttss都可以空着不写
    • app.json里改一下navigationBarTitleText用来显示标题栏名称
    • project.config.json里面填一下appid和projectname就行
  • 在pages文件夹里写
    • index.ttml文件里写网页结构,语法和html相似,但关键字不一样
    • index.js文件,用来写函数
    • index.ttss文件用来写index网页的样式

4.个位计算器的demo

  • 实现功能:两个个位数字的+-*/运算,有两个按钮计算、随机,点击随机会自动生成不同数字和运算符,点击计算会根据当前运算式显示结果
  • index.ttml
    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
    <view class="intro">Welcome to Sc-test</view>
    <view class="content">
    <!--显示块-->
    <view class="content_up_1">
    <picker class="calculation" value="{{index_1}}" range="{{array}}" data-value="1" bindchange="bindPickerChange" bindcancel="bindPickerCancel">
    <view class="picker">
    {{array[index_1]}}
    </view>
    </picker>
    <picker class="calculation" value="{{cal_num}}" range="{{cal_array}}" data-value="1" bindchange="bindPickerChange" bindcancel="bindPickerCancel">
    <view class="picker">
    {{cal_array[cal_num]}}
    </view>
    </picker>
    <picker class="calculation" value="{{index_2}}" range="{{array}}" data-value="1" bindchange="bindPickerChange" bindcancel="bindPickerCancel">
    <view class="picker">
    {{array[index_2]}}
    </view>
    </picker>
    </view>
    <!--
    <view>
    <button type="primary" bindtap="func1">页面主操作 Normal</button>
    <button type="primary" loading="true">页面主操作 Loading</button>
    <button type="primary" disabled="true">页面主操作 Disabled</button>
    </view>
    -->
    <view class="content_up_1">
    <view class="calculation_submit" bindtap="bindSubmit">计算</view>
    <view class="calculation_random" bindtap="bindRandom">随机</view>
    <!-- <view class="calculation_clear" bindtap="bindClear">清空</view> -->
    </view>

    <view class="content_down">
    <view class="text">{{result}}</view>
    </view>
  • index.js
    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
    38
    39
    40
    41
    const app = getApp()
    var that

    Page({
    data: {
    array: [
    1, 2, 3, 4, 5, 6, 7, 8, 9, 10
    ],
    cal_array: [
    '+', '-', '*', '/',
    ],
    index_1: 2,
    index_2: 0,
    cal_num: 0,
    result: '',
    },
    onLoad: function () {
    console.log('Welcome to Mini Code')
    },

    bindSubmit: function(e){
    var temple
    if(this.data.cal_array[this.data.cal_num] == '+') temple = this.data.array[this.data.index_1] + this.data.array[this.data.index_2]
    if(this.data.cal_array[this.data.cal_num] == '-') temple = this.data.array[this.data.index_1] - this.data.array[this.data.index_2]
    if(this.data.cal_array[this.data.cal_num] == '*') temple = this.data.array[this.data.index_1] * this.data.array[this.data.index_2]
    if(this.data.cal_array[this.data.cal_num] == '/') temple = this.data.array[this.data.index_1] / this.data.array[this.data.index_2]
    this.setData({
    result: temple,
    })
    },

    bindRandom: function (e) {
    this.setData({
    index_1: Math.floor(Math.random() * 10),//下标,0到9的随机整数
    index_2: Math.floor(Math.random() * 10),//下标,0到9的随机整数
    cal_num: Math.floor(Math.random() * 4),//下标,0到2的随机整数
    result: '',
    })
    },

    })
  • index.ttss
    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
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    .intro {
    margin: 30px;
    text-align: center;
    }

    .my-button {
    border-radius: 20px;
    }
    .my-button:after {
    border-color: #f00;
    border-radius: 40px; /* 需要设置为按钮圆角的两倍 */
    }

    .my-button-2 {
    border: 1px solid;
    }
    .my-button-2:after {
    display: none;
    }

    .content {
    display: flex;
    flex-direction: column; /*orientation 排版 column:垂直 row:水平*/
    }

    .content_up{
    width: max-content;
    height: 300rpx;
    }

    .content_up_1{
    margin-top: 20rpx;
    width: max-content;
    display: flex;
    flex-direction: row; /*orientation 排版 column:垂直 row:水平*/
    align-items: center;
    justify-content: center;
    text-align: center;
    }

    .picker{
    height: 80rpx;
    color:#585858;
    text-align: center;
    justify-content: center;
    align-items: center;
    display: flex;
    }

    .calculation_random{
    width: 155rpx;
    height: 80rpx;
    border-radius:8rpx;
    margin-left: 22rpx;
    background: rgba(83,217,105,1);
    color:#ffffff;
    text-align: center;
    justify-content: center;
    align-items: center;
    display: flex;
    }

    .calculation_submit{
    width: 155rpx;
    height: 80rpx;
    border-radius:8rpx;
    margin-left: 22rpx;
    background: rgb(3, 78, 16);
    color:#ffffff;
    text-align: center;
    justify-content: center;
    align-items: center;
    display: flex;
    }

    .calculation{
    width: 158rpx;
    height: 80rpx;
    border-radius:8rpx;
    margin-left: 22rpx;
    border:1rpx solid rgba(209,209,209,1);
    background: #F9F9F9;
    }

    .text{
    height: 80rpx;
    color:#585858;
    text-align: center;
    justify-content: flex-start;
    align-items: center ;
    margin-left: 20rpx;
    display: flex;
    }

5.抖音小程序与后端交互

  • 前端js部分(写在某个函数里面的)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    const task = tt.request({
    url: '127.0.0.1:8080/index/bar', // 目标服务器url
    dataType: 'string',
    success: (res) => {
    this.setData({
    result: res.data,
    })
    },
    fail: (res) => {
    console.log('get失败')
    this.setData({
    err_inf: res.errMsg,
    })
    },
    });
  • 后端部分
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    func main() {
    router := gin.Default()
    router.GET("/index/bar", response)
    router.Run()
    }
    func response(c *gin.Context) {
    str := "123456789"
    c.String(200, str)
    fmt.Println(str)
    }

目录

一、安装

一、安装

1.在Goland控制台上输入以下语句安装gin

1
go get -u github.com/gin-gonic/gin

如果出现网络错误,就分别执行下述语句后再重新安装

1
2
3
4
# 设置goproxy.io代理
go env -w GOPROXY="https://goproxy.io"
# 设置GO111MOUDLE
go env -w GO111MODULE="on"

示例

1.基础网页demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package main

import (
"github.com/gin-gonic/gin"
)

func main() {
router := gin.Default() //router是一个 *engine类型
router.GET("/get", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "use get method"})
})
router.Run()
}
//运行后访问localhost:4000/get,会显示一个JSON页面内容是message: "use get method"
  • router := gin.Default()声明并创建名为router的路由
  • router.GET(“/get”, func(c *gin.Context) {
      c.JSON(200, gin.H{"message": "use get method"})
    
    })是访问触发时,c.JSON()返回一个状态码是200(200等价于http.StatusOK),响应内容是一个JSON格式字符串的响应
    • “.GET”表示用GET方式来处理访问”/get”的请求
    • func(c *gin.Context) {
      c.JSON(200, gin.H{“message”: “use get method”})
      }执行函数gin.Context,其内封装了request和response,其中c是变量名可以随意更改
      • 注意gin.H的H是一个map结构,不是结构体

2.不同的http请求格式示例

1
2
3
4
5
6
7
8
9
router := gin.Default()
router.GET("/get", func(c *gin.Context) { c.JSON(200, gin.H{"message": "use get method"}) })
router.POST("/post", func(c *gin.Context) { c.JSON(200, gin.H{"message": "use post method"}) })
router.PUT("/put", func(c *gin.Context) { c.JSON(200, gin.H{"message": "use put method"}) })
router.DELETE("/delete", func(c *gin.Context) { c.JSON(200, gin.H{"message": "use delete method"}) })
router.PATCH("/patch", func(c *gin.Context) { c.JSON(200, gin.H{"message": "use patch method"}) })
router.HEAD("/head", func(c *gin.Context) { c.JSON(200, gin.H{"message": "use head method"}) })
router.OPTIONS("/options", func(c *gin.Context) { c.JSON(200, gin.H{"message": "use options method"}) })
router.Run()

3.切换输出的格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
router.GET("/json", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "return json data"})
})

router.GET("/string", func(c *gin.Context) {
c.String(200, "message %s", "return string data")
})

router.GET("/yaml", func(c *gin.Context) {
arr := [][]string{
{"one", "two", "three"},
{"four", "five", "six"},
}
c.YAML(200, arr)
})

router.GET("/xml", func(c *gin.Context) {
person := struct { //声明一个匿名结构体
Name string
Age int
}{"Jane", 20}
c.XML(200, fmt.Sprintln(person))
})

4.获取url路径中的参数

  • 定义,:name即表示把出现在这个位置的字符赋值给name属性,最后用c.Params读取
    1
    2
    3
    router.GET("/user/:name/:age/:addr/:sex", func(c *gin.Context) {
    c.JSON(200, fmt.Sprintln(c.Params))
    })
  • 使用
    1
    2
    3
    4
    //若输入的url为http://localhost:8080/user/jane/20/beijing/female?id=999&height=170&wigth=100

    //输出
    "[{name jane} {age 20} {addr beijing} {sex female}]\n"
  • 获取某个指定值的写法
    1
    2
    3
    4
    router.GET("/user/:name/:age/:addr/:sex", func(c *gin.Context) {
    age := c.Param("age")
    c.JSON(200, age)
    })

5.获取url请求中的参数

  • 定义
    1
    2
    3
    4
    5
    6
    router.GET("/user/:name/:age/:addr/:sex", func(c *gin.Context) {
    id := c.Query("id")
    height := c.Query("height")
    wight := c.Query("wight")
    c.JSON(200, gin.H("height": height, "id": id, "wight": wight)}
    })
  • 使用
    1
    2
    3
    4
    //若输入的url为http://localhost:8080/user/jane/20/beijing/female?id=999&height=170&wigth=100

    //输出
    {"height":"170","id":"999","wight":"100"}

6.输出html文件

  • 路由写法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    package main

    import (
    "github.com/gin-gonic/gin"
    )

    func main() {
    router := gin.Default()
    router.LoadHTMLGlob("tem/*")
    router.GET("/index", func(c *gin.Context) {
    c.HTML(200, "index.html", gin.H{"title": "测试", "ce": "123456"})
    })
    router.Run()
    }
  • 根目录\tmp\index.html写法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>{{.title}}</title>
    </head>
    <body>
    fgkjdskjdsh{{.ce}}
    </body>
    </html>
  • 最终会在localhost:8080/index渲染成以下网页
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>测试</title>
    </head>
    <body>
    fgkjdskjdsh123456
    </body>
    </html>

7.访问不同路径时的分离函数写法,下述代码无论是访问/demo、/test还是/aaaa都会去执行response,这种写法比之前的简简洁多

1
2
3
4
5
6
7
8
9
10
func response(c *gin.Context) {
c.JSON(200, gin.H{"message": "hello world"})
}
func main() {
router := gin.Default()
router.GET("/demo", response)
router.GET("/test", response)
router.GET("/aaaa", response)
router.Run()
}

8.gin的前后端交互写法(以接受token为例)

  • 前端
    1
    2
    3
    4
    5
    6
    7
    8
    <script src="https://cdn.dingxiang-inc.com/fe/common/jquery/1.9.1/jquery.min.js"></script>

    $.ajax({
    type:"GET",
    url:"http://127.0.0.1:8080/index/bar",
    dataType:"text",
    data: { token: token}
    });
  • 后端
    1
    2
    3
    4
    5
    6
    7
    8
    9
    func main(){
    router := gin.Default()
    router.GET("/index/bar", response)
    }

    func response(c *gin.Context){
    token := c.Query("token") //从这里之后就可以用token的值了,注意是string类型
    .....
    }

9.测试时,显示字符串用法

1
2
3
4
5
6
func response(c *gin.Context){
str1 := "str01"
str2 := "str02"
c.String(200, str1 + str2 + "!")
}
//最终会在页面上显示str01str02!

目录

一、安装和基本概念

二、示例

三、测试

四、xorm库操作mysql

五、后端开发思路

六、常用工具

七、踩坑

一、安装和基本概念

1.在Goland控制台上输入以下语句安装gin

1
2
go get -u github.com/gin-gonic/gin
//加-u的区别是,如果本地的包版本太低会顺便更新,不加-u的话只要本地有包就会不采取任何措施

如果出现网络错误,就分别执行下述语句后再重新安装

1
2
3
4
# 设置goproxy.io代理
go env -w GOPROXY="https://goproxy.io"
# 设置GO111MOUDLE
go env -w GO111MODULE="on"

2.几个内置的中间件

  • gin.Logger(),用于日志
  • gin.Recovery(),用于恢复恐慌panic()保持程序运行,然后返回500

3.gin.Default()定义的默认使用了Recovery和Logger中间件

  • 而用gin.New()定义的则是不使用任何中间件
  • 中间件的使用语法如下
    1
    router.Use(gin.Logger())
阅读全文 »