gin框架

感谢大家的关注和支持,大家一起进步呀

前言

Gin是一个用Go(Golang)编写的轻量级HTTP web框架,以其运行速度快、API友好和封装优雅著称。Gin框架支持RESTful风格的API设计,允许开发者使用URL定位资源,并通过HTTP请求类型(如GET、POST、PUT、DELETE等)描述操作。

  • Gin框架的主要特点包括:

  • 高性能‌:
    基于Radix树的路由,内存占用小,速度快。
    使用了httprouter,速度提高了近40倍。

  • 易用性‌:

  • API设计简洁明了,易于学习和使用。
    支持多种数据格式的响应,包括JSON、XML、HTML等。
    ‌灵活性‌:

  • 支持中间件,可以对请求进行预处理和后处理。
    支持路由组,可以更好地组织路由。

  • 错误处理‌:

  • 提供了一种方便的方法来收集HTTP请求期间发生的所有错误。
    ‌可扩展性‌:

  • 内置渲染为JSON、XML和HTML提供了易于使用的API。
    允许开发者自定义模板函数,增强模板的灵活性和功能。

1.Gin框架的路由

Gin框架提供了丰富的路由功能,包括基本路由、路由组、命名路由等。开发者可以轻松地定义各种HTTP请求的处理逻辑,并通过路由参数、查询参数等方式获取请求数据。

2.Gin框架的重定向

重定向实现的两种方式
给匿名函数命名,拆出实现

3.Gin框架的中间件

中间件是Gin框架中的一个重要概念,它允许开发者在请求处理流程中的不同阶段插入自定义的逻辑。中间件可以用于日志记录、身份验证、请求验证等多种场景。Gin框架支持全局中间件和局部中间件,可以根据需要灵活配置。
c.Next()
c.About()

4.注意事项

在使用Gin框架时,应确保Go语言版本符合要求(通常需要Go 1.13及以上版本)。
在处理错误和异常情况时,应合理使用panic和recover机制,以避免程序崩溃和数据丢失。
在开发Web应用时,应关注安全性问题,如防止SQL注入、跨站脚本攻击(XSS)等。
总的来说,Gin框架是一个功能强大、易于使用的Go语言Web框架,适合用于开发各种规模的Web应用。

5.gin开发知识点

5.1请求方法

GET
POST
DELETE
PUT

5.2状态码

1xx
2xx 成功相关
3xx 重定向
4xx 客户端请求相关
5xx 服务器相关

5.3前后端分离

前端  vue 好像的页面,接收后端数据,渲染到页面
后端  gin 处理前端的请求,编写接口,供前端调用

5.4交互方式:

ajax jquery
axios vue
表单

5.5参数获取 content-type

  1. url query查询子字符串参数 根据不同类型参数进行参数绑定
  2. form 参数,post表单参数
  3. json 参数
  4. url param 动态参数

5.6万能的参数获取方式

tag 首字母大写对应上
要传指针

5.7restful API 开发规范

5.8数据库

mysql
redis
mongdb

5.9第三方包

调用别人的日志

5.10测试工具

postman
自己搭建页面,发ajax 这就是前端开发

5.11nginx 部署相关

前端静态文件部署  
后端部署 

6.Gin框架的安装和使用

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

导入
import "github.com/gin-gonic/gin"
main.go
package main

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

// 主函数入口
func main() {
	// 创建一个默认的路由引擎
	r := gin.Default()

	// GET :请求方式;/ping 路径 访问时地址栏输入
	//  func(c *gin.Context) 请求进来时执行匿名函数
	r.GET("/ping", func(c *gin.Context) {
		// c 实例化参数,,里面封装了gin的方法
		// c.JSON:返回JSON格式数据
		// http.StatusOK 状态码
		//gin.H 是一个便捷的地图(map)类型,
		//gin.H 实际上是 map[string]interface{} 的别名,这意味着它可以存储任何类型的值,并且键是字符串类型。
		c.JSON(http.StatusOK, gin.H{
			"message": "pong",
		})
	})

	// 启动HTTP服务,默认在0.0.0.0:8080启动服务
	r.Run()

}

7.需求与实现

// 文件上传 单文件 多文件

// 重定向 未定义的路由返回统一界面

// 给匿名函数命名拆出

// 路由组 路由组嵌套 也可以分文件

// 中间件
    局部注册
    在匿名函数前加 中间件()
    全局注册
    中间件的使用
    r.use(中间件())
    c.Set("name", "root") 设置值
    name := c.MustGet("name").(string) 取值


// 启动多个服务

7.1上传文件

前端
注意属性:multiple name="avatar" name="files"

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <title>上传文件示例</title>
</head>
<body>
<form action="/upload" method="post" enctype="multipart/form-data">
    <input type="file" name="avatar">
    <input type="submit" value="上传">
</form>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Upload Multiple Files</title>
</head>
<body>
<h1>Upload Multiple Files</h1>
<form action="/uploads" method="post" enctype="multipart/form-data">
    <input type="file" name="files" multiple>
    <button type="submit">Upload</button>
</form>
</body>
</html>
package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"net/http"
	"path/filepath"
)

// 上传按钮
//点击上传

// 后端存在哪里

func main() {
	r := gin.Default()
	// 加载模板
	r.LoadHTMLFiles("templates/upload.html")
	r.LoadHTMLFiles("templates/uploads.html")
	// 返回界面
	r.GET("/upload", func(c *gin.Context) {
		c.HTML(http.StatusOK, "upload.html", nil)
	})
	r.GET("/uploads", func(c *gin.Context) {
		c.HTML(http.StatusOK, "uploads.html", nil)
	})

	// upfile
	r.POST("/upload", func(c *gin.Context) {
		// 接收文件 保存到本地
		// 单文件
		f, err := c.FormFile("avatar")
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{
				"message": err.Error(),
			})
			return
		}
		// 保存到指定目录
		dst := "upload/" + f.Filename
		err = c.SaveUploadedFile(f, dst)
		if err != nil {
			fmt.Println("出错啦")
			fmt.Println(err.Error())
			return
		}

		// 返回相应
		c.JSON(http.StatusOK, gin.H{
			"message": fmt.Sprintf("%s uploaded success!", f.Filename),
		})
	})

	// upfile
	r.POST("/uploads", func(c *gin.Context) {
		// 接收文件 保存到本地
		//  多文件
		form, err := c.MultipartForm()
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{
				"message": err.Error(),
			})
			return
		}
		files := form.File["files"]
		for _, file := range files {
			fmt.Println(file.Filename)
			err = c.SaveUploadedFile(file, filepath.Join("upload", file.Filename))
			if err != nil {
				fmt.Println("出错啦")
				fmt.Println(err.Error())
				return
			}

		}
		// 返回相应
		c.JSON(http.StatusOK, gin.H{
			"message": fmt.Sprintf("%d files uploaded success!", len(files)),
		})
	})
	// 重定向
	r.GET("/abc", func(c *gin.Context) {
		c.Redirect(http.StatusMovedPermanently, "http://www.baidu.com/")

	})
	r.GET("/abed", func(c *gin.Context) {
		c.Request.URL.Path = "/uploads"
		r.HandleContext(c)
	})

	r.GET("/aaa", aaaHandeler)

	r.NoRoute(func(c *gin.Context) {
		c.String(http.StatusNotFound, "没有这个网页")
	})

	r.Run()
}

func aaaHandeler(c *gin.Context) {
	fmt.Println("xxxxxxx")
	c.Redirect(http.StatusMovedPermanently, "http://www.baidu.com/")

}

7.2路由组

package main

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

func main() {
	// 创建一个默认的 Gin 引擎
	r := gin.Default()

	// 创建一个路由组
	api := r.Group("/api")
	{
		// 在组内添加 GET 请求路由
		api.GET("/user", func(c *gin.Context) {
			c.JSON(200, gin.H{
				"message": "Get user",
			})
		})

		// 在组内添加 POST 请求路由
		api.POST("/user", func(c *gin.Context) {
			c.JSON(200, gin.H{
				"message": "Post user",
			})
		})

		// 你可以为组添加更多的路由
		api.PUT("/user", func(c *gin.Context) {
			c.JSON(200, gin.H{
				"message": "Put user",
			})
		})

		api.DELETE("/user", func(c *gin.Context) {
			c.JSON(200, gin.H{
				"message": "Delete user",
			})
		})
	}

	// 另一个路由组
	v1 := r.Group("/v1")
	{
		v1.GET("/ping", func(c *gin.Context) {
			c.JSON(200, gin.H{
				"message": "pong",
			})
		})

		// 你可以在组内嵌套组
		stats := v1.Group("/stats")
		{
			stats.GET("/cpu", func(c *gin.Context) {
				c.JSON(200, gin.H{
					"message": "cpu stats",
				})
			})

			stats.GET("/memory", func(c *gin.Context) {
				c.JSON(200, gin.H{
					"message": "memory stats",
				})
			})
		}
	}

	// 启动 Gin 引擎
	r.Run(":8080") // 监听并在 0.0.0.0:8080 上启动服务
}


7.3中间件

package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"log"
	"time"
)

func CostTime(format string) gin.HandlerFunc {
	return func(c *gin.Context) {
		begin := time.Now()
		fmt.Println(begin.Format(format))
		//c中设置值,后续处理函数可以拿到
		c.Set("name", "root")
		// 调用该请求处理剩余的程序
		c.Next()
		// 不调用该请求处理剩余的程序
		// c.Abort() 遇到这个程序不在往下走
		//计算耗时
		cost := time.Since(begin)
		log.Panicln(cost)
	}

}

func main() {
	r := gin.Default()
	r.GET("/a", CostTime("2024-12-12"), func(c *gin.Context) {
		name := c.MustGet("name").(string)
		log.Println(name)
		fmt.Println(name)
		c.JSON(200, gin.H{
			"name": name,
		})

	})

	r.Run()
}

7.4请求参数 返回参数 重定向 非法页面处理

package main

import (
   "encoding/json"
   "fmt"
   "github.com/gin-gonic/gin"
   "net/http"
)

type Login struct {
   User     string `json:"user" form:"user" binding:"require"`
   Password string `json:"password"  form:"password" binding:"require"`
}

// 主函数入口
func main() {
   // 创建一个默认的路由引擎
   r := gin.Default()

   // GET :请求方式;/ping 路径 访问时地址栏输入
   //  func(c *gin.Context) 请求进来时执行匿名函数
   r.GET("/hello", func(c *gin.Context) {
   	// c 实例化参数,,里面封装了gin的方法
   	// c.JSON:返回JSON格式数据
   	// http.StatusOK 状态码
   	//gin.H 是一个便捷的地图(map)类型,
   	//gin.H 实际上是 map[string]interface{} 的别名,这意味着它可以存储任何类型的值,并且键是字符串类型。
   	c.JSON(http.StatusOK, gin.H{
   		"user": gin.H{
   			"id":   123,
   			"name": "John Doe",
   		},
   		"message": "Hello, world!",
   	})
   })
   r.Any("/home", func(context *gin.Context) {
   	// 根据请求的方法做处理
   	if context.Request.Method == http.MethodGet {
   		context.String(http.StatusOK, "欢迎来到首页")
   	}
   })
   r.GET("/login", func(c *gin.Context) {
   	// 结构体
   	var msg struct {
   		Name    string `json:"user"`
   		Pwd     string `json:"password"`
   		IsLogin int    `json:"is_login"`
   	}
   	msg.Name = "root"
   	msg.Pwd = "123456"
   	msg.IsLogin = 1 // 1表示成功登录
   	c.JSON(http.StatusOK, msg)
   })
   r.GET("/sms_login/search", func(c *gin.Context) {
   	// 结构体
   	var msg struct {
   		Name    string `json:"username"`
   		Pwd     string `json:"password"`
   		IsLogin string `json:"is_login"`
   	}

   	// 查询参数获取 sms_login/search?username=xx&password=1234
   	// 查询参数获取 sms_login/search?password=1234
   	username := c.DefaultQuery("username", "游客")
   	password := c.Query("password")
   	msg.Name = username
   	msg.Pwd = password
   	msg.IsLogin = "ok" // 1表示成功登录
   	c.JSON(http.StatusOK, msg)
   })

   // form表单
   r.POST("/sms_login/search", func(c *gin.Context) {
   	// 结构体
   	var msg struct {
   		Name    string `json:"username"`
   		Pwd     string `json:"password"`
   		IsLogin string `json:"is_login"`
   	}

   	username := c.DefaultPostForm("username", "游客")
   	password := c.PostForm("password")
   	fmt.Println(password)
   	msg.Name = username
   	msg.Pwd = "*******"
   	msg.IsLogin = "ok" // 1表示成功登录
   	c.JSON(http.StatusOK, msg)
   })

   // 获取json参数
   r.POST("/json", func(c *gin.Context) {
   	// 结构体
   	var msg struct {
   		Name    map[string]interface{} `json:"username"`
   		Pwd     string                 `json:"password"`
   		IsLogin string                 `json:"is_login"`
   	}
   	user, _ := c.GetRawData() //请求体中拿数据
   	var username map[string]interface{}
   	// 反序列化
   	_ = json.Unmarshal(user, &username)

   	msg.Name = username

   	msg.IsLogin = "ok" // 1表示成功登录
   	c.JSON(http.StatusOK, msg)
   })

   // 获取path参数
   r.GET("/path/:username/:password", func(c *gin.Context) {
   	// 结构体
   	var msg struct {
   		Name    string `json:"username"`
   		Pwd     string `json:"password"`
   		IsLogin string `json:"is_login"`
   	}

   	username := c.Param("username")
   	password := c.Param("password")
   	fmt.Println(password)
   	msg.Name = username
   	msg.Pwd = "*******"
   	msg.IsLogin = "ok" // 1表示成功登录
   	c.JSON(http.StatusOK, msg)
   })

   // 参数绑定
   r.POST("/loginJson", func(c *gin.Context) {
   	var login Login
   	if err := c.ShouldBind(&login); err != nil {
   		fmt.Printf("login info:%#v\n\n", login)
   		c.JSON(http.StatusOK, gin.H{
   			"user":     login.User,
   			"password": login.Password,
   		})
   	} else {
   		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
   	}

   })
   // 重定向
   r.GET("/abc", func(c *gin.Context) {
   	// c.Redirect(http.StatusMovedPermanently, "http://www.baidu.com/")
   	c.Request.URL.Path = "/upload"
   	r.HandleContext(c)
   })
   r.NoRoute(func(c *gin.Context) {
   	c.String(http.StatusNotFound, "没有这个网页")
   })
   // 启动HTTP服务,默认在0.0.0.0:8080启动服务
   r.Run(":8080")

}

小结

基于gin框架的简单使用就到此结束了,本文主要是概念性内容,和一些重要开发经验,框架就是个半成品,需要去熟悉它的源码执行流程,希望大家能够有所收获 。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值