当前位置: 首页 > news >正文

gin 框架初始教程文档

一 、gin 入门

1. 安装gin :下载并安装 gin包:

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

2. 将 gin 引入到代码中:

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

3.初始化项目

go mod init gin

4.完整代码

package mainimport "github.com/gin-gonic/gin"func main() {r := gin.Default()r.GET("/ping", func(c *gin.Context) {c.JSON(200, gin.H{"message": "pong",})})r.Run()
}

5.启动项目

go run main.go  # 运行 main.go 并且在浏览器中访问 0.0.0.0:8080/ping

6.效果图

二、基础知识

  1. go get -u

参数介绍:

  • -d 只下载不安装

  • -f 只有在你包含了 -u 参数的时候才有效,不让 -u 去验证 import 中的每一个都已经获取了,这对于本地 fork 的包特别有用

  • -fix 在获取源码之后先运行 fix,然后再去做其他的事情

  • -t 同时也下载需要为运行测试所需要的包

  • -u 强制使用网络去更新包和它的依赖包

  • -v 显示执行的命

三、gin测试用例

  1. AsciiJSON 生成具有转义的非 ASCII 字符的 ASCII-only JSON。

package mainimport ("github.com/gin-gonic/gin""net/http"
)func main()  {r:=gin.Default()r.GET("/someJson", func(c *gin.Context) {data:=map[string]interface{}{"lang":"go 语言","tag":"<br>",}c.AsciiJSON(http.StatusOK,data)})r.Run(":8081")
}

为什么 浏览器和 终端命令行curl打印出来的结果格式不一样?gin.AsciiJSON

答:编码问题

  1. 绑定HTML复选框

package mainimport "github.com/gin-gonic/gin"type myForm struct {Colors []string `form:"colors[]"`
}func formHandler(c *gin.Context) {var fakeForm myFormc.ShouldBind(&fakeForm)c.JSON(200, gin.H{"color": fakeForm.Colors})
}func innerHandler(c *gin.Context) {c.HTML(200, "form.html", nil)
}func main() {r := gin.Default()r.LoadHTMLGlob("views/*")r.GET("/", innerHandler)r.POST("/", formHandler)r.Run(":8082")
}

views/form.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<form action="/" method="POST"><p>Check some colors</p><label for="red">Red</label><input type="checkbox" name="colors[]" value="red" id="red"><label for="green">Green</label><input type="checkbox" name="colors[]" value="green" id="green"><label for="blue">Blue</label><input type="checkbox" name="colors[]" value="blue" id="blue"><input type="submit">
</form>
</body>
</html>
  1. 绑定查询字符串或表单数据

package mainimport ("github.com/gin-gonic/gin""log""time"
)
//表单字符串
type PersonString struct {Name     string    `form:"name"`Address  string    `form:"address" `Birthday time.Time `form:"birthday" time_format:"2006-01-02" time_utc:"1"`
}//请求json格式
type PersonJson struct {Name     string    `json:"name"`Address  string    `json:"address"`Birthday time.Time `json:"birthday" time_format:"2006-01-02" time_utc:"1"`
}func startPage(c *gin.Context) {var person PersonStringerr := c.Bind(&person)//ShouldBind 与 Bind 打印结果一样//err:=c.ShouldBind(&person)if err == nil {log.Println(person.Name)log.Println(person.Address)log.Println(person.Birthday)log.Println("Binding success...")} else {log.Println("Binding failed...")log.Println(err)}var personJson PersonJsonerrJson := c.BindJSON(&personJson)if errJson == nil {log.Println(personJson.Name)log.Println(personJson.Address)//log.Println(personJson.Birthday)log.Println("BindJson success...")} else {log.Println("BindJson failed...")log.Println(errJson)}c.String(200, "success")
}
func main() {log.Println("Hello World")route := gin.Default()route.GET("/testing", startPage)route.Run(":8083")
}

请求:

string:

 curl -X GET "http://0.0.0.0:8083/testing?name=appleboy&address=xyz&birthday=2023-03-15"
打印:结果
success   

josn:

curl -X GET "http://0.0.0.0:8083/testing" --data '{"name":"JJ", "address":"xyz"}' -H "Content-Type:application/json"结果:success

效果图:

  1. 绑定uri

package mainimport "github.com/gin-gonic/gin"type Person struct {ID   string `uri:"id" building:"required,uuid"`Name string `uri:"name" building:"required"`
}func main() {r := gin.Default()r.GET("/:name/:id", func(c *gin.Context) {var person Personif err := c.ShouldBindUri(&person); err != nil {c.JSON(400, gin.H{"msg": err})return}c.JSON(200, gin.H{"name": person.Name, "uuid": person.ID})})r.Run(":8080")}

  1. 控制log 高亮输出,默认开启高亮

//强制log 高亮
gin.ForceConsoleColor()//关闭log高亮
//gin.DisableConsoleColor()

6.自定义http配置:(监听端口,读写时间,最大读写字节数)


func main() {r := gin.Default()r.GET("/ping", func(c *gin.Context) {c.String(200, "pong")})//两行作用一样,谁先执行谁生效//r.Run(":8080")//http.ListenAndServe(":8081",r)s := &http.Server{Addr:           ":8084",Handler:        r, //实例句柄ReadTimeout:    10 * time.Second,WriteTimeout:   10 * time.Second,MaxHeaderBytes: 1 << 20,}s.ListenAndServe()
}
  1. 自定义log文件

func main() {r := gin.New()r.Use(gin.LoggerWithFormatter(func(params gin.LogFormatterParams) string {return fmt.Sprintf("%s - [%s] \"%s %s %s %d %s \"%s\" %s\"\n",params.ClientIP,params.TimeStamp.Format(time.RFC3339),params.Method,params.Path,params.Request.Proto,params.StatusCode,params.Latency,params.Request.UserAgent(),params.ErrorMessage,)}))r.Use(gin.Recovery())r.GET("/ping", func(c *gin.Context) {c.String(200, "pong")})r.Run(":8080")
}
  1. 自定义中间件

//自定义中间件
func logger() gin.HandlerFunc {return func(c *gin.Context) {t := time.Now()//设置变量c.Set("lxw", "this is string")c.Set("lxwInt", 123456789)//请求前c.Next()//请求后latency := time.Since(t)log.Println(latency) //花费时间//获取发送的codestatusCode := c.Writer.Status()log.Println(statusCode)}
}
func main() {r := gin.New()r.Use(logger()) //引用(相当于include)r.GET("/test", func(c *gin.Context) {/*** MustGet returns the value for the given key if it exists, otherwise it panics.返回给定键的值(如果存在),否则会死机*/varInt := c.MustGet("lxwInt").(int) //int 是对变量lxwInt 的限制要求,若不是int则报错varString := c.GetString("lxw")log.Println(varInt,varString)})r.Run(":8080")
}
  1. 自定义验证器

//自定义验证器
//输入和输出日期必填;输出日期大于输入日期;输入和输出日期符合自定的验证器(日期需在今天日期之后)type Booking struct {CheckIn  time.Time `form:"check_in" binding:"required,bookabledate" time_format:"2006-01-02"`CheckOut time.Time `form:"check_out" binding:"required,gtfield=CheckIn bookabledate" time_format:"2006-01-02"`
}//验证器
var bookableDate validator.Func = func(fl validator.FieldLevel) bool {date, ok := fl.Field().Interface().(time.Time)if ok {today := time.Now()if today.After(date) {return false}}return true
}func getBookable(c *gin.Context) {var b Bookingif err := c.ShouldBindWith(&b, binding.Query); err == nil {c.JSON(http.StatusOK, gin.H{"message": "book data is validate"})} else {c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})}
}func main() {r := gin.Default()if v, ok := binding.Validator.Engine().(*validator.Validate); ok {v.RegisterValidation("bookabledate", bookableDate)}r.GET("/bookable", getBookable)r.Run(":8080")
}

请求地址:输入和输出日期必填;输出日期大于输入日期;输入和输出日期符合自定的验证器(日期需在今天日期之后)

http://0.0.0.0:8080/bookable?check_in=2023-02-08&check_out=2023-03-09

  1. 定义路由日志格式

//定义路由日志格式
func main() {r := gin.Default()gin.DebugPrintRouteFunc = func(httpMethod, absolutePath, handlerName string, nuHandlers int) {log.Printf("endpoint %v %v %v %v\n", httpMethod, absolutePath, handlerName, nuHandlers)}r.POST("/aaa", func(c *gin.Context) {c.JSON(http.StatusOK, "aaa")})r.GET("/bbb", func(c *gin.Context) {c.JSON(http.StatusOK, "bbb")})r.GET("/ccc", func(c *gin.Context) {c.JSON(http.StatusOK, "ccc")})r.Run()
}
  1. 优雅的关机或重启

//优雅的关机或重启
func main() {r := gin.Default()r.GET("/", func(c *gin.Context) {time.Sleep(5 * time.Second)c.String(http.StatusOK, "welcome server")})srv := &http.Server{Addr:    ":8080",Handler: r,}go func() {//服务连接:打印链接错误信息if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {log.Fatalf("listen: %s \n", err)}}()//等待中断信号优雅关闭服务器(设置5秒的超时时间)quit := make(chan os.Signal)signal.Notify(quit, os.Interrupt)<-quitlog.Println("shutdown server...")ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)defer cancel()//关机失败原因if err := srv.Shutdown(ctx); err != nil {log.Fatal("server shutdown:", err)}log.Println("server exiting")
}
  1. 路由组


func main() {r := gin.Default()v1 := r.Group("/v1"){v1.GET("/aa", loginEndpoint)v1.GET("/bb", exit)}r.Run()
}func loginEndpoint(c *gin.Context) {c.String(200,"hello")
}func exit( context2 *gin.Context)  {context2.String(200,"world")
}
  1. 记录日志到文件和控制台(默认直接打印在控制台)

func main() {//禁用控制台颜色,将日志写入文件时不需要控制台颜色(加不加无所谓)//gin.DisableConsoleColor()//创建日志文件fileName, _ := os.Create("gin.log")//将日志并发写入文件gin.DefaultWriter = io.MultiWriter(fileName)//将日志同时写入文件和控制台//gin.DefaultWriter = io.MultiWriter(fileName, os.Stdout)r := gin.Default()r.GET("/ping", func(c *gin.Context) {c.String(200, "pong")})r.Run()
}

参考:https://learnku.com/docs/gin-gonic/1.7/examples-bind-uri/11391

http://www.lryc.cn/news/21059.html

相关文章:

  • Maven的下载和安装【详细】
  • [数据结构]:04-循环队列(数组)(C语言实现)
  • buu [GWCTF 2019]BabyRSA 1
  • codeforces 1669F
  • 高数考试必备知识点
  • [蓝桥杯] 二分与前缀和习题练习
  • SpringMvc中HandlerAdapter组件的作用
  • FreeRTOS优先级翻转
  • 服务器部署—部署springboot之Linux服务器安装jdk和tomcat【建议收藏】
  • golang项目----家庭收支记账软件
  • 中国LNG市场投资机会研究
  • Elasticsearch:索引数据是如何完成的
  • 处理器管理
  • 跟着我从零开始入门FPGA(一周入门系列)第五
  • 【第42天】Arrays.sort 与 Collections.sort 应用 | 整形数组与集合的排序
  • LeetCode第334场周赛
  • 基于深度学习的三维重建网络PatchMatchNet(三):PatchMatchNet配置及代码主要运行流程
  • 【一天一门编程语言】设计一门编程语言,给出基础语法代码示例,SDK设计。
  • ubuntu 下 python 安装 venv
  • HTML#1快速入门
  • 【MySQL】事务隔离级别是怎么实现的?
  • JSP网上书店系统用myeclipse定制开发mysql数据库B/S模式java编程计算机网页
  • 配置 Haproxy 负载均衡群集
  • 计算机网络笔记 | 第一章:计算机网络概述(1.1-1.4小节知识点整理)
  • Flutter3引用原生播放器-Android篇
  • SerenityOS 操作系统类 Unix 操作系统
  • Bean作用域和生命周期
  • STM32笔记
  • 【论文阅读】基于LevelDB的分布式数据库研究
  • JavaScript高级 Iterator Generator