介绍(gin笔记第一期)

p.s.这是萌新自己自学总结的笔记,如果想学习得更透彻的话还是请去看大佬的讲解

目录

Gin 框架是一个基于 Go 语言的轻量级 Web 框架,它基于 Go 语言的 net/http 包进行开发,提供了高效、快速、易用的 Web 服务开发体验。

原生HTTP库缺点

go 复制代码
package main

import "net/http"
import "fmt"
import "io"

func Index(w http.ResponseWriter, r *http.Request) {
    fmt.Println(r.Method,r.URL.String())
    if r.Method == "GET" {
        byteData, _ := io.ReadAll(r.Body)
        fmt.Println(string(byteData))
    }
        w.Write([]byte("Hello, World!"))
    }

func main() {

    //访问服务
    http.HandleFunc("/index", Index)

    http.ListenAndServe("0.0.0.0:8080", nil)
}
复制代码
C:\Users\Lenovo>curl http://127.0.0.1:8080/index?key=123
Hello, World!

但是在实际项目中使用原生 go http 库那会非常不方便。

主要体现在:参数解析与验证、路由不明确、响应处理比较原始

gin使用

go 复制代码
package main
import "github.com/gin-gonic/gin"



func main() {
    //初始化
    r := gin.Default()

    //挂载路由
    r.GET("/index", func(c *gin.Context) {
         c.JSON(200, gin.H{
             "message": "Hello, World!",
         })

    })
    //绑定端口,启动服务
    r.Run(":8080")
}

响应

响应JSON

go 复制代码
package res

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

type Res struct {
	Code int    `json:"code"`
	Msg  string `json:"msg"`
	Data any    `json:"data"`
}

var codeMap = map[int]string{
	1001: "失败",
	1002: "大失败",
}

func response(c *gin.Context, code int, data any, msg string) {
	c.JSON(200, Res{
		Code: code,
		Msg:  msg,
		Data: data,
	})
}

func Ok(c *gin.Context, data any, msg string) {
	response(c, 0, data, msg)  
}

func OkWithData(c *gin.Context, data any) {
	Ok(c, data, "成功") 
}

func OkWithMsg(c *gin.Context, msg string) {
	Ok(c, nil, msg) 
}

func Fail(c *gin.Context, code int, data any, msg string) {
	response(c, code, data, msg)
}

func FailWithMsg(c *gin.Context, msg string) {
	response(c, 1001, nil, msg)
}

func FailWithCode(c *gin.Context, code int) {
	codeMsg, ok := codeMap[code]
	if !ok {
		codeMsg = "未知错误"
	}
	response(c, code, nil, codeMsg) 
}
go 复制代码
package main
import "golang/res"
import "github.com/gin-gonic/gin"



func main() {
    //初始化
    r := gin.Default()

    //挂载路由
    r.GET("/index", func(c *gin.Context) {
        // c.JSON(200, gin.H{
        //     "message": "Hello, World!",
        // })
        res.OkWithMsg(c, "这是一个成功的响应")
    })

    //挂载路由
    r.GET("/user", func(c *gin.Context) {
        res.OkWithData(c, gin.H{
            "name": "张三",
            "age": 30,
        })
    })



    //绑定端口,启动服务
    r.Run(":8080")


}

响应html

go 复制代码
package main

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



func main() {
    //初始化
    r := gin.Default()

    r.LoadHTMLGlob("templates/*")
    r.GET("/", func(c *gin.Context) {
        //可很方便修改标题
        c.HTML(200, "index.html", map[string]any{
            "title": "Gin框架示例",
        })
    })

    //绑定端口,启动服务
    r.Run(":8080")


}

响应文件

用于浏览器直接请求这个接口唤起下载

go 复制代码
package main

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

func main() {
    //初始化
    r := gin.Default()

    r.GET("/", func(c *gin.Context) {
        c.Header("Content-Type", "application/octet-stream") // 表示是文件流,唤起浏览器下载。一般设置了这个,就要设置文件名
        c.Header("Content-Disposition", "attachment; filename=res/res.go") // 用来指定下载下来的文件名
        c.File("res/res.go")
    })

    //绑定端口,启动服务
    r.Run(":8080")


}

}

前端唤起浏览器下载的本质
<a href="文件地址" download="文件名">文件下载</a>

响应静态文件

go 复制代码
package main

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



func main() {
    //初始化
    r := gin.Default()

    //加载静态文件
    //注意:静态文件的路径,不能再被路由使用了
    r.Static("st", "static")

    //绑定端口,启动服务
    r.Run(":8080")


}

请求

查询参数

?key=xxx&name=xxxx 这种就被称为查询参数

go 复制代码
package main

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


func main() {
    //初始化
    r := gin.Default()

    r.GET("/user/:id", func(c *gin.Context) {
        id := c.Param("id")//动态参数
        name := c.Query("name")//查询参数
        fmt.Printf("id: %s, name: %s\n", id, name)
    })

    //绑定端口,启动服务
    r.Run(":8080")


}
}

表单参数

go 复制代码
package main

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


func main() {
    //初始化
    r := gin.Default()

    r.POST("users", func(c *gin.Context) {
	name := c.PostForm(key:"name")
	age, ok := c.GetPostForm(key:"age")//判断是否传入了这个参数,无论是否有值
	fmt.Println(name)
	fmt.Println(age, ok)
    })

    //绑定端口,启动服务
    r.Run(":8080")


}

上传文件

go 复制代码
package main

import (
	"fmt"
	"io"
	"os"

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

func main() {
	//初始化
	r := gin.Default()

	r.POST("users", func(c *gin.Context) {
		fileHeader, err := c.FormFile(name: "file")
		if err != nil {
			fmt.Println(err)
			return
		}
		fmt.Println(fileHeader.Filename) // 文件名
		fmt.Println(fileHeader.Size)     // 文件大小,单位是字节

		// file, _ := fileHeader.Open()
		// byteData, _ := io.ReadAll(file)

		// err = os.WriteFile(name: "qill7.jpg", byteData, perm: 0666)
		// fmt.Println(err)

        err = c.SaveUploadedFile(fileHeader, "uploads/xxx/yyy/"+fileHeader.Filename)
        fmt.Println(err)
	})

	//绑定端口,启动服务
	r.Run(":8080")
}

多文件上传

go 复制代码
package main

import (
	"fmt"

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

func main() {
    r := gin.Default()
    r.POST(relativePath: "users", func(c *gin.Context) {
        form, err := c.MultipartForm()
        if err != nil {
            fmt.Println(err)
            return
        }
        for _, headers := range form.File {
            for _, header := range headers {
                c.SaveUploadedFile(header, "uploads/"+header.Filename)
            }
        }
    })
    r.Run(addr: ":8080")
}

bind绑定器

Gin 的 Bind 绑定器主要用于解析和验证 HTTP 请求中的参数,将请求数据绑定到 Go 的结构体(struct)中。

主要用途:

  1. 数据绑定
    自动从请求中提取数据并填充到结构体:
    从 URL 查询参数绑定
    从 POST 表单数据绑定
    从 JSON/XML 请求体绑定
    从 URL 路径参数绑定
  2. 数据验证
    结合验证标签对数据进行验证

查询参数

go 复制代码
package main

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

func main() {
	r := gin.Default()
	
	r.GET("/", func(c *gin.Context) {
		// 定义结构体
		type User struct {
			Name string `form:"name"`
			Age  int    `form:"age"`
		}
		
		var user User
		err := c.ShouldBindQuery(&user)
		fmt.Println(user, err)
		
		// 返回JSON响应
		c.JSON(200, gin.H{
			"name": user.Name,
			"age":  user.Age,
		})
	})
	
	r.Run(":8080")
}

路径参数

go 复制代码
type User struct {
	Name string `uri:"name"`
	ID   int    `uri:"id"`
}

var user User
err := c.ShouldBindUri(&user)
fmt.Println(user, err)

表单参数

注意:不能解析 x-www-form-urlencoded 的格式

go 复制代码
type User struct {
	Name string `form:"name"`
	Age  int    `form:"age"`
}

var user User
err := c.ShouldBind(&user)
fmt.Println(user, err)

JSON参数

go 复制代码
type User struct {
	Name string `form:"name"`
	Age  int    `form:"age"`
}

var user User
err := c.ShouldBindJSON(&user)
fmt.Println(user, err)

Header参数

go 复制代码
type User struct {
    Name      string `header:"Name"`
    Age       int    `header:"Age"`
    UserAgent string `header:"User-Agent"`
}
var user User
err := c.ShouldBindHeader(&user)
fmt.Println(user, err)

内置规则

对传入的参数进行为空校验、枚举校验等

go 复制代码
// 字段必传,并且不做校验该字段
required 必填字段,如:binding:"required"

// 针对字符串的长度
min 最小长度,如:binding:"min=5"
max 最大长度,如:binding:"max=10"
len 长度,如:binding:"len=6"

// 针对数字的大小
eq 等于,如:binding:"eq=3"
ne 不等于,如:binding:"ne=12"
gt 大于,如:binding:"gt=18"
gte 大于等于,如:binding:"gte=18"
lt 小于,如:binding:"lt=18"
lte 小于等于,如:binding:"lte=18"

// 针对同字段的值
eqfield 等于其他字段的值,如:Password string `binding:"eqfield=Password"`
nefield 不等于其他字段的值

// 忽略字段,如:binding:"-" 或者不写
-

// 枚举 只要是red或green
oneof=red green

自定义验证器

go 复制代码
v.RegisterValidation(tag:"fip", func(fl validator.FieldLevel) bool {
    fmt.Println(a...:"fl.Field(): ", fl.Field())
    fmt.Println(a...:"fl.FieldName(): ", fl.FieldName())
    fmt.Println(a...:"fl.StructFieldName(): ", fl.StructFieldName())
    fmt.Println(a...:"fl.Parent(): ", fl.Parent())
    fmt.Println(a...:"fl.Top(): ", fl.Top())
    fmt.Println(a...:"fl.Param(): ", fl.Param())
ip, ok := fl.Field().Interface().(string)
if ok && ip != "" {
    // 传了值就去校验是不是IP地址
    ipObj := net.ParseIP(ip)
    return ipObj != nil
}
return false

})

路由与中间件

go 复制代码
func main() {
r := gin.Default()
r.POST()
r.GET()
r.PUT()
r.PATCH()
r.DELETE()
r.Any(relativePath: "")
}

路由分组

go 复制代码
package main

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

func main() {
	r := gin.Default()
	
	apiGroup := r.Group("api")

	//绑定全局中间件
	apiGroup.Use()


	//可以分组多个同名的路由
	//apiGroup3 := r.Group("api")
	//apiGroup2 := r.Group("api")

	//绑定实现方法
	UserGroup(apiGroup)
	
	r.Run(":8080")
}

//实现方法
func UserView(c *gin.Context) {
	path := c.Request.URL
	fmt.Println(path)
}


func UserGroup(r *gin.RouterGroup) {
	r.GET("users", UserView)
	r.POST("users", UserView)
	r.DELETE("users", UserView)
	r.PUT("users", UserView)
}


加入中间件

go 复制代码
package main

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

func Home(c *gin.Context) {
	fmt.Println("Home")
	c.String(200, "Home")
}

//中间件
func M1(c *gin.Context) {
	fmt.Println("M1 请求前(Let freedom ring!)")
	c.Next()
	fmt.Println("M1 请求后,即响应部分")
}

//中间件
func M2(c *gin.Context) {
	fmt.Println("M2 请求")
	c.Next()//放行
	//c.Abort() 拦截
	fmt.Println("M2 响应")
}

//局部中间件
func main() {
	r := gin.Default()
	r.GET("/",M1,M2,Home)
	r.Run(":8080")
}
相关推荐
鱼鳞_2 小时前
Java学习笔记_Day32(IO流字符集字符流)
java·笔记·学习
lkbhua莱克瓦242 小时前
ZogginWeb 电脑端沉浸式记单词功能优化升级业务需求文档
笔记·电脑
kobesdu2 小时前
【ROS2实战笔记-4】Gazebo:从通信桥接到性能瓶颈相关技术梳理
笔记·机器人·ros·gazebo
EQ-雪梨蛋花汤2 小时前
【笔记】安卓毛玻璃效果(Blur)实现笔记(使用BlurView)(结尾附:源码)
android·笔记
zore_c2 小时前
【C++】C++——类的默认成员函数(构造、析构、拷贝构造函数)
java·c语言·c++·笔记·算法·排序算法
夜瞬10 小时前
NLP学习笔记01:文本预处理详解——从清洗、分词到词性标注
笔记·学习·自然语言处理
中屹指纹浏览器11 小时前
指纹浏览器内核级渲染伪造技术:Canvas/WebGL/AudioContext深度伪造与检测绕过实战
经验分享·笔记
-Springer-11 小时前
STM32 学习 —— 个人学习笔记11-1(SPI 通信协议及 W25Q64 简介 & 软件 SPI 读写 W25Q64)
笔记·stm32·学习
LN花开富贵11 小时前
【ROS】鱼香ROS2学习笔记一
linux·笔记·python·学习·嵌入式·ros·agv