Gin是一个go编写的轻量级http web框架,运行速度非常快,性能高效
Gin最擅长Api接口的高并发
下载安装:
使用:
package main
import "github.com/gin-gonic/gin"
func main() {
// 创建一个默认的路由引擎
r := gin.Default()
// 配置路由
r.GET("/", func(ctx *gin.Context) {
ctx.String(200, "Hello world")
})
r.GET("/news", func(ctx *gin.Context) {
ctx.String(200, "aaaa")
})
// r.Run() 启动HTTP服务,默认在 0。0.0.0:8080 启动服务
r.Run(":8080") //启动一个web服务
}
golang程序的热加载
所谓也加载就是当我们对代码进行修改时,程序能够自动重载加载并执行。
beego中我们可以使用官方给我们提供的bee工具来热加载项目,但是gin中没有官方提供的热加载工具。
工具1:
工具2:
fresh
fresh
若vscode报以下错误
在vscode终端输入:
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine")
更新路径变量
请求类型
r.GET("/news", func(ctx *gin.Context) {
ctx.String(200, "aaaa")
})
r.POST("/add", func(ctx *gin.Context) {
ctx.String(200, "这是一个post请求主要用于增加数据")
})
r.PUT("/edit", func(ctx *gin.Context) {
ctx.String(200, "这是一个put请求 主要用于编辑数据")
})
r.DELETE("/delete", func(ctx *gin.Context) {
ctx.String(200, "这是一个DELETE请求 用于删除数据")
})
post等请求可以使用postman来测试
如果使用诸如 http.StatusOK 之类的常量,则需要引入 net/http 包:
import "net/http"
返回值返回字符串
r := gin.Default()
r.GET("/", func(ctx *gin.Context) {
ctx.String(http.StatusOK, "值:%v", "首页")
})
r.Run()
返回json
type Test struct {
Title string `json:"title"`
Desc string `json:"desc"`
Content string `json:"content"`
}
r.GET("/json", func(ctx *gin.Context) {
ctx.JSON(http.StatusOK, map[string]interface{}{
"success": true,
"msg": "hello gin",
})
})
r.GET("/json2", func(ctx *gin.Context) {
ctx.JSON(http.StatusOK, gin.H{
"success": true,
"msg": "hello gin",
})
})
r.GET("/json3", func(ctx *gin.Context) {
a := &Test{
Title: "Test",
Desc: "描述",
Content: "内容",
}
ctx.JSON(http.StatusOK, a)
})
返回jsonp
// 响应jsonp请求
r.GET("/jsonp", func(ctx *gin.Context) {
a := &Test{
Title: "Test-jsonp",
Desc: "描述",
Content: "内容",
}
ctx.JSONP(http.StatusOK, a)
})
返回xml
r.GET("/xml", func(ctx *gin.Context) {
ctx.XML(http.StatusOK, gin.H{
"success": true,
"msg": "hello gin",
})
})
返回html以及渲染页面
r.GET("/news", func(ctx *gin.Context) {
ctx.HTML(http.StatusOK, "news.html", gin.H{
"title": "我是后台的数据",
})
})
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h2>{{.title}}</h2>
</body>
</html>
HTML渲染
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
type Article struct {
Title string
Content string
}
func main() {
r := gin.Default()
// 加载模板
r.LoadHTMLGlob("templates/**/*")
r.GET("/", func(ctx *gin.Context) {
ctx.HTML(http.StatusOK, "default/index.html", gin.H{
"title": "首页",
})
})
r.GET("/news", func(ctx *gin.Context) {
news := &Article{
Title: "新闻标题",
Content: "新闻详情",
}
ctx.HTML(http.StatusOK, "default/new.html", gin.H{
"title": "新闻页面",
"news": news,
})
})
r.GET("/admin", func(ctx *gin.Context) {
ctx.HTML(http.StatusOK, "admin/index.html", gin.H{
"title": "后台首页",
})
})
r.GET("/admin/news", func(ctx *gin.Context) {
news := &Article{
Title: "新闻标题",
Content: "新闻详情",
}
ctx.HTML(http.StatusOK, "admin/new.html", gin.H{
"title": "后台新闻页面",
"news": news,
})
})
r.Run()
}
{{define "admin/index.html"}}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h2>这是后台首页</h2>
</body>
</html>
{{end}}
{{define "admin/new.html"}}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h2>这是新闻页面</h2>
</body>
</html>
{{end}}
{{define "default/index.html"}}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h2>{{.title}}</h2>
</body>
</html>
{{end}}
{{define "default/new.html"}}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h2>{{.title}}</h2>
<p>
{{.news.Title}}
</p>
<p>
{{.news.Content}}
</p>
</body>
</html>
{{end}}
变量
<!-- 定义变量 -->
{{$t := .title}}
<br>
<h4>
{{$t}}
</h4>
比较函数
eq 如果arg1 == arg2则返回真
ne 如果arg1 != arg2则返回真
lt 如果arg1 < arg2则返回真
le 如果arg1 <= arg2则返回真
gt 如果arg1 > arg2则返回真
ge 如果arg1 >= arg2则返回真
条件判断
<!-- 条件判断 -->
{{if ge .score 60}}
<p>及格</p>
{{else}}
<p>不及格</p>
{{end}}
range循环遍历
r.GET("/", func(ctx *gin.Context) {
ctx.HTML(http.StatusOK, "default/index.html", gin.H{
"title": "首页",
"score": 100,
"hobby": []string{"吃饭", "睡觉", "写代码"},
"newsList": []interface{}{
&Article{
Title: "新闻标题1",
Content: "新闻详情1",
}, &Article{
Title: "新闻标题2",
Content: "新闻详情2",
},
"testSlice": []string{},
},
})
})
<!-- 循环遍历数据 -->
<ul>
{{range $key,$value := .hobby}}
<li>{{$key}}----{{$value}}</li>
{{end}}
</ul>
<ul>
{{range $key,$value := .newsList}}
<li>{{$key}}----{{$value.Title}}----{{$value.Content}}</li>
{{end}}
</ul>
With
<!-- with解构结构体 -->
{{with .news}}
{{.Title}}
{{.Content}}
{{end}}
预定义函数
{{len .title}}等
自定义模板函数
func UnixToTime(timestamp int) string {
fmt.Println(timestamp)
t := time.Unix(int64(timestamp), 0)
return t.Format("2006-01-02 15:04:05")
}
// 自定义函数要放在加载模板前面
r.SetFuncMap(template.FuncMap{
"UnixToTime": UnixToTime,
})
<!-- 自定义模板函数 -->
{{UnixToTime .date}}
嵌套template
{{define "public/page_header.html"}}
<style>
h1{
background: #000;
color:rgb(245, 249, 248);
text-align: center;
}
</style>
<h1>
我是一个公共标题----{{.title}}
</h1>
{{end}}
{{define "default/new.html"}}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
{{template "public/page_header.html" .}}
<h2>{{.title}}</h2>
<p>
{{.news.Title}}
</p>
<p>
{{.news.Content}}
</p>
</body>
</html>
{{end}}
静态文件服务
// 配置静态web目录 第一个参数表示路由,第二个参数表示映射目录
r.Static("/static", "./static")
h1{
background: #000;
color: aliceblue;
text-align: center;
}
h2{
color: aqua;
}
路由传值
Get 请求传值
r.GET("/get", func(ctx *gin.Context) {
username := ctx.Query("username")
age := ctx.Query("age")
page := ctx.DefaultQuery("page", "1")
ctx.JSON(http.StatusOK, gin.H{
"username": username,
"age": age,
"page": page,
})
})
Post 请求传值
{{define "default/user.html"}}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="static/css/base.css">
</head>
<body>
<form action="/doAppUser" method="post">
用户名:<input type="text" name="username"><br><br>
密码:<input type="password" name="password"><br><br>
年龄:<input type="text" name="age"><br><br>
<input type="submit" value="提交">
</form>
</body>
</html>
{{end}}
// post请求
r.GET("/user", func(ctx *gin.Context) {
ctx.HTML(http.StatusOK, "default/user.html", gin.H{})
})
// 获取表单post的数据
r.POST("/doAppUser", func(ctx *gin.Context) {
username := ctx.PostForm("username")
password := ctx.PostForm("password")
age := ctx.DefaultPostForm("age", "20")
ctx.JSON(http.StatusOK, gin.H{
"username": username,
"password": password,
"age": age,
})
})
获取 GET POST 传递的数据绑定到结构体
// 获取 GET POST 传递的数据绑定到结构体
// http://localhost:8080/getUser?username=zhangsan&password=123123
r.GET("/getUser", func(ctx *gin.Context) {
user := &UserInfo{}
if err := ctx.ShouldBind(&user); err == nil {
fmt.Printf("%#v", user)
ctx.JSON(http.StatusOK, user)
} else {
ctx.JSON(http.StatusOK, gin.H{
"err": err.Error(),
})
}
})
获取Post Xml数据
// 获取Post Xml数据
r.POST("/xml", func(ctx *gin.Context) {
article := &Article{}
xmlSliceData, _ := ctx.GetRawData()
fmt.Println(xmlSliceData)
if err := xml.Unmarshal(xmlSliceData, &article); err == nil {
ctx.JSON(http.StatusOK, article)
} else {
ctx.JSON(http.StatusBadRequest, gin.H{
"err": err.Error(),
})
}
})