Gin框架

第一个简单gin程序

func hello(c *gin.Context) {
	c.String(200, "love")
	c.JSON(200, gin.H{
		"age":  "20",
		"name": "zhy",
	})
}
func main() {
	r := gin.Default()
	r.GET("/hello", hello)
	r.Run()
}

2 登录页面

**login.html

<body>
        <form action="/login" METHOD="post">
            用户名:<input TYPE="text" name="username"><br>
            密 码:<INPUT TYPE="password" name="password"><br>
            <input TYPE="submit" VALUE="登录">
        </form>
</body>

welcome.html**

<body>
        欢迎{{.username}} <br>
        请记住你的密码{{.password}}
</body>

main.go

func main() {
	r := gin.Default()
	r.LoadHTMLGlob("templates/*")
	r.GET("/login", func(context *gin.Context) {
		context.HTML(200, "login.html", gin.H{})
	})
	r.POST("/login", func(context *gin.Context) {
		username := context.PostForm("username")
		password := context.PostForm("password")
		context.HTML(200, "welcome.html", gin.H{
			"username": username,
			"password": password,
		})
	})
	r.Run()
}

在这里插入图片描述

-------------------------------------------------------------------
在这里插入图片描述

问答:虽然二者路由都是 /login 但因为一个是get方法,一个是 post 方法,所以没有影响。
执行顺序 先访问 GET方法里的/login 加载 login.html文件,因为此文件中的表单操作 跳转是发出post请求给/login ,因此 就会执行post方法里的welcome.html

3. GET请求参数

func main() {
	engine := gin.Default()
	engine.GET("/params", func(context *gin.Context) {
		//获取url中名为username的值
		username := context.Query("username")
		//获取url中名为password的值  123为默认值 如果没有密码 默认输出123
		password := context.DefaultQuery("password", "123")
		context.JSON(200, gin.H{
			"username": username,
			"password": password,
		})
	})
	engine.Run()
}

访问 http://localhost:8080/params?username=zhy&password=456
在这里插入图片描述

4. 路径参数 restful风格 c.Param(“key”)

http://localhost:8080/testPath/zhy/22/大三

//http://localhost:8080/testPath/zhy/22/大三
engine.GET("/testPath/:name/:age/:grade", func(context *gin.Context) {
		param := context.Param("name")
		s := context.Param("age")
		s2 := context.Param("grade")
		context.JSON(200, gin.H{
			"param": param,
			"age":   s,
			"grade": s2,
		})
	})

在这里插入图片描述

5. 既有GET也有POST

query.html

<body>
    <form action="/search?page=5" method="post">
        请输入查询关键字:<input type="text" name="key" >
        <input type="submit" value="查询">
    </form>
</body>

main.go

func main() {
	engine := gin.Default()
	engine.LoadHTMLGlob("templates/*")
	engine.GET("/gosearch", func(context *gin.Context) {
		context.HTML(200, "query.html", nil)
	})
	engine.POST("/search", func(context *gin.Context) {
		query := context.DefaultQuery("page", "0")
		form := context.PostForm("key")
		context.JSON(200, gin.H{
			"page": query,
			"key":  form,
		})
	})
	engine.Run()
}

在这里插入图片描述

**-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
在这里插入图片描述

6. form表单处理

test_form.html

<body>
    <h1>用户注册页面</h1>

    <form action="/register" method="post">
        用户名:<input type="text" name="username" ><br>
        密 码:<input type="password" name="password" ><br>
        爱好:
<!--   checkbook 复选框-->
        游泳<input type="checkbox" name="hobby" value="swimming">
        篮球<input type="checkbox" name="hobby" value="basketball">
        足球<input type="checkbox" name="hobby" value="football">
        <br>
        性别:
<!--        radio  单选按钮--><input type="radio" name="gender" id="1" value="male"><input type="radio" name="gender" id="2" value="female">
        <br>
<!--        下拉列表-->
        城市:<select name="city" >
        <option value="beijing">北京</option>
        <option value="shanghai">上海</option>
        <option value="xianyang">咸阳</option>
    </select>
        <br>
        <input type="submit" value="注册">
    </form>
</body>

main.go

func main() {
	engine := gin.Default()
	engine.LoadHTMLGlob("templates/*")
	engine.GET("/goregister", func(context *gin.Context) {
		context.HTML(200, "test_form.html", nil)
	})
	engine.POST("/register", func(context *gin.Context) {
		username := context.PostForm("username")
		password := context.PostForm("password")
		hobby := context.PostFormArray("hobby") //这个需要注意一下 和其他不一样
		gender := context.PostForm("gender")
		city := context.PostForm("city")
		context.JSON(200, gin.H{
			"username": username,
			"password": password,
			"hobby":    hobby,
			"gender":   gender,
			"city":     city,
		})
	})
	engine.Run()
}

在这里插入图片描述
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
在这里插入图片描述

7. Gin数据绑定

7.1 绑定Form表单

test_fom 同上
main.go

type User struct {
	//对应表单中的username
	Username string   `form:"username"`
	Password string   `form:"password"`
	Hobby    []string `form:"hobby"`
	Gender   string   `form:"gender"`
	City     string   `form:"city"`
}

func main() {
	engine := gin.Default()
	engine.LoadHTMLGlob("templates/*")
	engine.GET("/register", func(context *gin.Context) {
		context.HTML(200, "test_form.html", nil)
	})
	engine.POST("/register", func(c *gin.Context) {
		var u User
		//将post过来的数据绑定到结构体
		c.ShouldBind(&u)
		c.String(200, "form data is %s", u)
	})
	engine.Run()
}

在这里插入图片描述

-----------------------------------------------------------------------------------------------------------------------------------------------------------------
在这里插入图片描述

8. 绑定查询参数

main.go

type Admin struct {
	//对应表单中的username
	Username string `form:"username"`
	Password string `form:"password"`
}

func main() {
	engine := gin.Default()
	engine.LoadHTMLGlob("templates/*")
	//http://localhost:8080/testGetBind?username=ZHY&password=123465
	engine.GET("/testGetBind", func(context *gin.Context) {
		var a Admin
		err := context.ShouldBind(&a)
		if err != nil {
			log.Fatal(err)
		}
		context.String(200, "admin data is : %s ", a)
	})
	engine.Run()
}

浏览器输入 :http://localhost:8080/testGetBind?username=ZHY&password=123465
在这里插入图片描述

9. 路径请求参数绑定

main.go

type Admin2 struct {
	//对应表单中的username  uri  对应 url
	Username string `uri:"username"`
	Password string `uri:"password"`
}
func main() {
	engine := gin.Default()
	engine.LoadHTMLGlob("templates/*")
	//http://localhost:8080/testurlBind/winnie/3.1415926
	engine.GET("/testurlBind/:username/:password", func(context *gin.Context) {
		var a2 Admin2
		//url绑定
		err := context.ShouldBindUri(&a2)
		if err != nil {
			log.Fatal(err)
		}
		context.String(200, "admin data is : %s ", a2)
	})
	engine.Run()
}

在这里插入图片描述

10. Gin访问静态文件集成BootStrap框架

https://getbootstrap.com/ 下载 框架 css js 文件夹 找这里的Compiled CSS and JS download

test_static.html

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <!--    下面两行是加载-->
    <link rel="stylesheet" href="/ass/css/bootstrap.min.css">
    <script src="/ass/js/bootstrap.min.js"></script>
</head>
<body>
<!--可以去这里找相关组件 https://getbootstrap.com/docs/5.1/components/pagination/-->
<!--可以查看相关css文件。-->
    <div class="container">
        <div class="btn-group" role="group" aria-label="Basic example">
            <button type="button" class="btn btn-primary">Left</button>
            <button type="button" class="btn btn-primary">Middle</button>
            <button type="button" class="btn btn-primary">Right</button>
        </div>
        <nav aria-label="Page navigation example">
            <ul class="pagination">
                <li class="page-item"><a class="page-link" href="#">Previous</a></li>
                <li class="page-item"><a class="page-link" href="#">1</a></li>
                <li class="page-item"><a class="page-link" href="#">2</a></li>
                <li class="page-item"><a class="page-link" href="#">3</a></li>
                <li class="page-item"><a class="page-link" href="#">Next</a></li>
            </ul>
        </nav>
    </div>
</body>
</html>

main.go

func main() {
	engine := gin.Default()
	engine.LoadHTMLGlob("templates/*")
	//加载静态文件 第一个参数 相对路径,第二个参数 文件名路径
	engine.Static("/ass", "./assets")
	engine.GET("/static", func(context *gin.Context) {
		context.HTML(200, "test_static.html", nil)
	})
	engine.Run()

}

在这里插入图片描述

11. Gin BasicAuth中间件

gin提供了BasicAuth中间件,用来对网站资源的访问保护

//模拟私人数据
var secrets = gin.H{
	"foot":   gin.H{"email": "foot@qq.com", "phone": 123456789},
	"basket": gin.H{"email": "basket@qq.com", "phone": 987654321},
	"Winnie": gin.H{"email": "Winnie@qq.com", "phone": 3.1415926},
}

func Handler(c *gin.Context) {
	//获取用户,它是由BasicAuth中间件设置的
	//AuthUserKey 是 "user" 的名称
	//MustGet 返回 给定键的值
	user := c.MustGet(gin.AuthUserKey).(string)
	fmt.Println(user) //打印user 拿到的是 登录用户
	//如果secrets里的键和user的值对应 那么将该键的值返回给secret
	if secret, ok := secrets[user]; ok {
		c.JSON(200, gin.H{"user": user, "secret": secret})
	} else {
		c.JSON(200, gin.H{"user": user, "secret": "NO SECRET:("})
	}
}
func main() {
	r := gin.Default()
	//这些用户数据 可以从数据库查询 gorm
	//BasicAuth,它接受 map[string]字符串作为参数,其中键是用户名,值是密码。
	//type Accounts map[string]string  Accounts为授权登录的用户/传递列表定义一个键/值
	group := r.Group("/admin")
	group.Use(gin.BasicAuth(gin.Accounts{ //路由分组中配置中间件
	//登陆的用户名,密码。用户名对应 secrets里的键名
		"foot":   "bar",
		"austin": "1234",
		"basket": "hello2",
		"Winnie": "zining",
	}))
	{
		group.GET("/secret1", Handler)
	}
	r.Run()
}

http://localhost:8080/admin/secret1

  1. 我们先拿"austin": "1234"来测试,因为austin不属于secrets里的键名
    在这里插入图片描述
    在这里插入图片描述

  2. 我们拿"Winnie": "zining"来测试,因为Winnie 属于secrets里的键名
    在这里插入图片描述
    在这里插入图片描述

11.1 中间件第二种配置方式

func main() {
	r := gin.Default()
	//这些用户数据 可以从数据库查询 gorm
	//BasicAuth,它接受 map[string]字符串作为参数,其中键是用户名,值是密码。
	//type Accounts map[string]string  Accounts为授权登录的用户/传递列表定义一个键/值
	group := r.Group("/admin", gin.BasicAuth(gin.Accounts{ //路由分组中配置中间件
		"foot":   "bar",
		"austin": "1234",
		"basket": "hello2",
		"Winnie": "zining",
	}))
	{
		group.GET("/secret1", Handler)
	}
	r.Run()
}

12. Gin cookie 使用

cookie是服务器向客户端写的一些数据,可以实现像自动登录等功能。

基于安全考虑,需要给cookie加上SecureHttpOnly属性HttpOnly比较好理解,设置httponly=true的cookie不能被js获取到,无法用document.cookie打出cookie内容,
Secure属性是说如果一个cookie被设置了secure=true,那么这个cookie只能用https协议发送给服务器,用HTTP协议是不发送的。

func handler(c *gin.Context) {
	//Cookie返回请求中提供的命名Cookie
	s, err := c.Cookie("username")
	if err != nil {
		s = "zhy"
		c.SetCookie("username", s, 60*60, "/", "localhost", false, true)
	}
	c.String(200, "测试cookie")
}
func main() {
	r := gin.Default()
	r.GET("/testcookie", handler)
	r.Run()
}

在这里插入图片描述

13. Gin使用Session

因为http是无状态、短链接,如何保存客户端和服务器直接的会话状态呢,可以用session
使用gin session中间件

import (
	"github.com/gin-contrib/sessions"
	"github.com/gin-contrib/sessions/cookie"
	"github.com/gin-gonic/gin"
)

func handler(c *gin.Context) {
	// 初始化session对象
	session := sessions.Default(c)
	//获得session值  看是否 "我是" 的值为  "Winnie" 
	if session.Get("我是") != "Winnie" {
		//设置
		session.Set("我是", "Winnie")
		//保存
		session.Save()
	}
	c.JSON(200, gin.H{"我是": session.Get("我是")})
}
func main() {
	r := gin.Default()
	// 初始化一个存储引擎,参数为密钥,用于加解密
	// 创建基于cookie的存储引擎,secret 参数是用于加密的密钥
	store := cookie.NewStore([]byte("secret"))
	// 设置Sessions中间件,参数 mysession,指的是 session 的名字,也是cookie的名字
	// store是前面创建的存储引擎,我们可以替换成其他存储引擎
	r.Use(sessions.Sessions("mysession", store))
	r.GET("/session", handler)
	r.Run()
}

在这里插入图片描述

14. Gin实现restful风格的CRUD

CRUD说的就是增查改删

type User struct {
	Uid  int    `json:"uid"`
	Name string `json:"name"`
	Age  int    `json:"age"`
}

var users = make([]User, 3)

func init() {
	u1 := User{1, "张三", 20}
	u2 := User{2, "五四", 21}
	u3 := User{3, "王麻子", 22}
	users = append(users, u1)
	users = append(users, u2)
	users = append(users, u3)
	fmt.Println(users)
}

//根据ID查找用户
func Find(uid int) (*User, int) {
	for index, value := range users {
		if value.Uid == uid {
			return &value, index
		}
	}
	return nil, -1
}

//根据 url中uid位置的值 查找用户
func FindUser(c *gin.Context) {
	param := c.Param("uid")
	atoi, _ := strconv.Atoi(param)
	find, i := Find(atoi)
	c.JSON(200, gin.H{
		"USER":   find,
		"INDEDX": i,
	})

}

//增添
func AddUser(c *gin.Context) {
	u4 := User{4, "Winnie", 23}
	users = append(users, u4)
	c.JSON(200, users)
}

//删除
func DelUser(c *gin.Context) {
	//获取 url中 uid位置 的值
	param := c.Param("uid")
	//被转换为int类型。 查找 id
	id, _ := strconv.Atoi(param)
	// 找到id对应的在users中的 下标
	_, i := Find(id)
	//对当前位置进行覆盖   
	// 设有一切片值为 users[0 1 2 3 4 5 6 7] i=4
	//users[:4]=[0 1 2 3] 因为 s[:high] 从切片s的索引位置0到high处所得切片 len=high 
	//users[i+1:]=users[5:]=[5 6 7] 
	//append(users[:i], users[i+1:]...) 意思为 将users[5:]增添至users[:4]后面 从而覆盖掉了users[4]的值 从而达到删除作用
	users = append(users[:i], users[i+1:]...)
	c.JSON(200, users)
}

//修改
func UpdateUser(c *gin.Context) {
	uid := c.Param("uid")
	id, _ := strconv.Atoi(uid)
	user, index := Find(id)
	user.Name = "123"
	users[index] = *(user)
	c.JSON(200, users)
}
func main() {
	engine := gin.Default()
	engine.GET("/user/:uid", FindUser)
	engine.PUT("/user/:uid", UpdateUser)
	engine.DELETE("/user/:uid", DelUser)
	engine.POST("/user/", AddUser)
	engine.Run()
}

15. 文件上传

test_upload.html

<body>
<form action="/upload" method="post" enctype="multipart/form-data">
    请你选择上传的文件:<input type="file" name="file">
    <br>
    <input type="submit" value="提交上传">
</form>
</body>
func upload(c *gin.Context) {
	//单文件
	//获取上传的文件 , "file" 对应 html里的 "file"
	file, _ := c.FormFile("file")
	log.Println(file.Filename) //file.Filename表示获取文件名称
	//上传文件到 项目根目录,使用原文件名
	//没有设置路径的话 默认上传至 根目录
	c.SaveUploadedFile(file, file.Filename)
	c.String(200, fmt.Sprintf("%s upload!", file.Filename))
}
func doupload(c *gin.Context) {
	c.HTML(200, "test_upload.html", nil)
}
func main() {
	engine := gin.Default()
	//限制处理该文件所占用的最大内存
	engine.MaxMultipartMemory = 8 << 20 //8 MiB
	engine.LoadHTMLGlob("templates/*")
	engine.GET("/upload", doupload)
	engine.POST("/upload", upload)
	engine.Run()
}

16.

17.

18.

19.

20.

21.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值