Go 语言 Gin框架入门| 青训营

104 阅读5分钟

 Gin入门 

  • Gin是一个golang的微框架,封装比较优雅,API友好,源码注释比较明确,具有快速灵活,容错方便等特点 
  • 对于Golang而言,web框架的依赖要远比Python,Java之类要小,自身的net/http足够简单,性能也非常不错 
  • 借助框架开发,不仅可以省去很多常用的封装带来的时间,也有助于团队的编码风格和形成规范. 

安装 

要安装Gin 软件包,需要先安装GO并设置Go工作区. 

 首先需要安装GO,然后可以使用GO命令安装Gin.在go.mod同级目录执行以下命令. 

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

Gin入门与源码 

 一共需要3步. 

 创建路由 

路由绑定 

启动监听

func main() {
	// 1. 创建路由
	r := gin.Default()
	// 2. 路由绑定
	r.GET("/", func(c *gin.Context) {
		c.String(200, "ok")
	})
	// 3. 启动监听
	fmt.Println("http://192.168.31.1:8080")
	r.Run(":8080")
}

gin核心概念 

  • Engine 容器对象,整个框架基础 
  • Engine.trees 负责存储路由和handle方法的映射,采用类似字典树的结构 
  • Engine.RouterGroup 其中Handlers存储着所有中间件
  • Context上下文对象,负责处理请求和回应,其中handlers是存储处理请求时中间件和处理方法的. 

gin 路由

无参路由 

不传递任何数据 

 func main() {
	// 1. 定义路由
	r := gin.Default()
	// 2. 定义路由
	r.GET("/hello", HelloHandler)
	// 3. 启动监听
	fmt.Println("http://192.168.31.1:8080/hello")
	r.Run(":8080")
}

func HelloHandler(c *gin.Context) {
	c.String(200, "hello world")
} 
  • gin 框架中采用的路由库是基于httprouter做的 
  • 因为虽然net/http这个包里有着默认路由,但是仍存在着不足,所以使用httprouter
  •  httprouter 是一个高性能、可扩展的HTTP路由,上面我们列举的net/http默认路由的不足,都被httprouter 实现 

Api传参 

func main() {
	// 1. 定义
	r := gin.Default()
	r.GET("/book/:id", GetBookHandler)
	fmt.Println("http://localhost:8080/")
	r.Run(":8080")
}

func GetBookHandler(c *gin.Context) {
	bookID := c.Param("id")
	fmt.Println(bookID, "------->")
	book := "你找的书:" + bookID + "已经找到\n"
	c.String(200, book)
} 

 Url传参 

  • URL参数可以通过DefaultQuery()或Query()方法获取

  • DefaultQuery()若参数不存在,返回默认值,Query()若不存在,返回空串

    func main() { r := gin.Default() r.GET("/user", UrlGetHandler) fmt.Println("http://192.168.31.1:8080/") r.Run(":8080") } func UrlGetHandler(c *gin.Context) { username := c.Query("username") password := c.Query("password") output := "你输入的用户名是:" + username + " 密码是:" + password c.String(200, output) }

设置默认值

 func main() {
	r := gin.Default()
	r.GET("/user", UrlGetHandler)
	fmt.Println("http://192.168.31.1:8080/")
	r.Run(":8080")
}
func UrlGetHandler(c *gin.Context) {
	username := c.Query("username")
	//password := c.Query("password")
	password := c.DefaultQuery("password", "你没有输入密码")
	output := "你输入的用户名是:" + username + "   密码是:" + password
	c.String(200, output)
} 

如果这里没有传值就会用默认值替代 如果传入值,那么就用传入的值. 

shouldBind 

用来解析Post请求中复杂的Json数据 

 func main() {
	r := gin.Default()
	r.POST("/user/login", LoginHandler)
	r.Run(":8080")
}

type Login struct {
	Username string `json:"username"`
	Password string `json:"password"`
}

func LoginHandler(c *gin.Context) {
	var login Login
	if err := c.ShouldBind(&login); err != nil {
		c.String(400, "err")
        return
  	}
	Code := login.Username + "  Login Succeeded!"
	c.String(200, Code)
} 

 也可以将某个参数设为必须 

 func main() {
	r := gin.Default()
	r.POST("/user/login", LoginHandler)
	r.Run(":8080")
}

type Login struct {
	Username string `json:"username" binding:"required"`
	Password string `json:"password" binding:"required"`
}

func LoginHandler(c *gin.Context) {
	var login Login
	if err := c.ShouldBind(&login); err != nil {
		fmt.Println(err)
		c.String(400, "err")
		return
	}
	Code := login.Username + "  Login Succeeded!"
	c.String(200, Code)
} 

当没有传该参数时就会报错

 数据返回Response 

 String字符串返回 

func main() {
	r := gin.Default()
	r.GET("/response", ResponseHandler)
	r.Run(":8080")
}
func ResponseHandler(c *gin.Context) {
	msg := "success response"
	c.String(200, msg)
} 

返回Json数据 

func main() {
	r := gin.Default()
	r.GET("/response", JsonHandler)
	r.Run(":8080")
}
func JsonHandler(c *gin.Context) {
	type Data struct {
		Msg  string `json:"msg"`
		Code int    `json:"code"`
	}
	d := Data{
		Msg:  "success",
		Code: 200,
	}
	c.JSON(200, d)
} 

直接通过gin.H返回 

直接用gin.H将json数据进行返回,返回效果和上面效果一样 

 func JsonHandler(c *gin.Context) {
	c.JSON(200, gin.H{
		"msg":  "success",
		"code": 200,
	})
} 

路由重定向

 func main() {
	r := gin.Default()
	r.GET("/response/json", JsonHandler)
	r.GET("/response/baidu", ResponseRedirHandler)
	r.Run(":8080")
}
func ResponseHandler(c *gin.Context) {
	msg := "success response"
	c.String(200, msg)
}
func JsonHandler(c *gin.Context) {
	c.JSON(200, gin.H{
		"msg":  "success",
		"code": 200,
	})
}
func ResponseRedirHandler(c *gin.Context) {
	c.Redirect(302, "https://www.baidu.com")
}

路由分发 

一个项目有非常多的模块,每个模块维护自己的路由.主路由在main.go中进行注册 

 初始化项目 

go mod init demo_route_layer		// 初始化项目
go mod tidy 				// 更新项目中使用的模块
go get github.com/gin-gonic/gin		// 下载go模块 

main.go 

import (
	"demo_route_layer/routers" // 导入本地模块
	"github.com/gin-gonic/gin"
)

func main() {
	r := gin.Default()
	// 注册路由
	routers.LoadUsers(r)
	routers.LoadBook(r)

	r.Run(":8080")
} 

routers/users.go

// 分层注册路由
func LoadUsers(r *gin.Engine) {
	r.GET("/user", UserHandler)

}

func UserHandler(c *gin.Context) {
	c.String(200, "用户模块分发")
} 

 routers/book 

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

func LoadBook(r *gin.Engine) {
	r.GET("/book", BooksHandler)
}
func BooksHandler(c *gin.Context) {
	c.String(200, "图书模块返回")
} 

会话处理

Cookie 

Cookie介绍 

  • HTTP是无状态协议,服务器不能记录浏览器的访问状态,也就是说服务器不能区分两次请求是否由同一个客户端发出 
  • Cookie就是解决HTTP协议无状态的方案之一,中文是小甜饼的意思 
  • Cookie实际上就是服务器保存在浏览器上的一段信息。浏览器有了Cookie之后,每次向服务器发送请求时都会同时将该信息发送给服务器,服务器收到请求后,就可以根据该信息处理请求 
  • Cookie由服务器创建,并发送给浏览器,最终由浏览器保存 

cookie用途 

测试服务端发送cookie给客户端,客户端请求时携带cookie 

Cookie缺点 

  • 不安全,明文
  • 增加带宽消耗 
  • 可以被禁用 
  • cookie数量有上限(每个浏览器不同) 

Sessions 

  • 简单的API:将其用作设置签名(以及可选的加密)cookie的简便方法。 
  • 内置的后端可将session存储在cookie或文件系统中。 
  • Flash消息:一直持续读取的session值。 
  • 切换session持久性(又称“记住我”)和设置其他属性的便捷方法。 
  • 旋转身份验证和加密密钥的机制。 
  • 每个请求有多个session,即使使用不同的后端也是如此。 
  • 自定义session后端的接口和基础结构:可以使用通用API检索并批量保存来自不同商店的session。