当前位置: 首页 > 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

相关文章:

gin 框架初始教程文档

一 、gin 入门1. 安装gin &#xff1a;下载并安装 gin包&#xff1a;$ go get -u github.com/gin-gonic/gin2. 将 gin 引入到代码中&#xff1a;import "github.com/gin-gonic/gin"3.初始化项目go mod init gin4.完整代码package mainimport "github.com/gin-go…...

Maven的下载和安装【详细】

文章目录一、什么是Maven&#xff1f;二、Maven的安装与配置2.1下载Maven安装包2.2配置Maven环境变量2.3验证三、Idea配置Maven3.1配置 setting.xml文件3.2Idea配置Maven一、什么是Maven&#xff1f; Apache Maven是个项目管理和自动构建工具&#xff0c;基于项目对象模型&…...

[数据结构]:04-循环队列(数组)(C语言实现)

目录 前言 已完成内容 循环队列实现 01-开发环境 02-文件布局 03-代码 01-主函数 02-头文件 03-QueueCommon.cpp 04-QueueFunction.cpp 结语 前言 此专栏包含408考研数据结构全部内容&#xff0c;除其中使用到C引用外&#xff0c;全为C语言代码。使用C引用主要是为了…...

buu [GWCTF 2019]BabyRSA 1

题目描述&#xff1a; import hashlib import sympy from Crypto.Util.number import *flag GWHT{******} secret ******assert(len(flag) 38)half len(flag) / 2flag1 flag[:half] flag2 flag[half:]secret_num getPrime(1024) * bytes_to_long(secret)p sympy.nextp…...

codeforces 1669F

题意: alice和bob从数组两边的吃糖果, 数组的值就是糖果重量 要求alice和bob吃的糖果重量必须一样, 输出能吃几个糖果 这题最先想到的是前后缀相加 模拟一个前缀和 和 后缀和 在n/2的位置向前找前缀和 在n/2的位置向后找后缀和 找到第一个前缀和后缀和的下标输出就好 …...

高数考试必备知识点

三角函数与反三角函数的知识点 正弦函数 ysin x&#xff0c; 反正弦函数 yarcsin x • y sin x&#xff0c; x∈R&#xff0c; y∈[–1&#xff0c;1]&#xff0c;周期为2π&#xff0c;函数图像以 x (π/2) kπ 为对称轴 • y arcsin x&#xff0c; x∈[–1&#xff0c;1]…...

[蓝桥杯] 二分与前缀和习题练习

文章目录 一、二分查找习题练习 1、1 数的范围 1、1、1 题目描述 1、1、2 题解关键思路与解答 1、2 机器人跳跃问题 1、2、1 题目描述 1、2、2 题解关键思路与解答 1、3 四平方和 1、3、1 题目描述 1、3、2 题解关键思路与解答 二、前缀和习题练习 2、1 前缀和 2、1、1 题目描述…...

SpringMvc中HandlerAdapter组件的作用

概述 我们在使用springMVC时&#xff0c;都知道其中不仅包含handlerMapping组件还包含handlerAdapter组件&#xff0c;为什么呢&#xff1f; springMVC请求流程图 HandlerAdapter组件使用了适配器模式 适配器模式的本质是接口转换和代码复用&#xff0c;这里使用适配器模式的…...

FreeRTOS优先级翻转

优先级翻转优先级翻转&#xff1a;高优先级的任务反而慢执行&#xff0c;低优先级的任务反而优先执行优先级翻转在抢占式内核中是非常常见的&#xff0c;但是在实时操作系统中是不允许出现优先级翻转的&#xff0c;因为优先级翻转会破坏任务的预期顺序&#xff0c;可能会导致未…...

服务器部署—部署springboot之Linux服务器安装jdk和tomcat【建议收藏】

我是用的xshell连接的云服务器&#xff0c;今天想在服务器上面部署一个前后端分离【springbootvue】项目&#xff0c;打开我的云服务器才发现&#xff0c;过期了&#xff0c;然后又买了一个&#xff0c;里面环境啥都没有&#xff0c;正好出一期教程&#xff0c;方便大家也方便自…...

golang项目----家庭收支记账软件

家庭收支记账软件实现基本功能(先使用面向过程&#xff0c;后面改成面向对象)项目代码实现改进面向过程源码面向对象源码utils包中main包中实现基本功能(先使用面向过程&#xff0c;后面改成面向对象) 编写文件TestMyAccount.go完成基本功能 功能一&#xff1a;先完成可以显示…...

中国LNG市场投资机会研究

中国LNG市场投资机会研究中国LNG市场是一个具有巨大潜力和发展机遇的市场&#xff0c;尤其是在政府大力推动清洁能源发展的背景下&#xff0c;LNG市场投资机会正在不断扩大。首先&#xff0c;政府大力支持LNG市场的发展。政府实施的“十三五”规划将LNG作为清洁能源的重要来源&…...

Elasticsearch:索引数据是如何完成的

在我在之前的文章 “Elasticsearch&#xff1a;彻底理解 Elasticsearch 数据操作” 文章中&#xff0c;我详细地描述了如何索引数据到 Elasticsearch 中。在今天的文章中&#xff0c;我想更进一步来描述这个流程。 Elasticsearch 是一个非常强大和灵活的分布式数据系统&#x…...

处理器管理

处理器状态处理器管理是操作系统中重要组成部分&#xff0c;负责管理、调度和分配计算机系统的重要资源——处理器&#xff0c;并控制程序执行由于处理器管理是操作系统最核心的部分&#xff0c;无论是应用程序还是系统程序&#xff0c;最终都要在处理器上执行以实现其功能&…...

跟着我从零开始入门FPGA(一周入门系列)第五

5、同步和异步设计 前面已有铺垫&#xff0c;同步就是与时钟同步。 同步就是走正步&#xff0c;一二一&#xff0c;该迈哪个脚就迈那个脚&#xff0c;跑的快的要等着跑的慢的。 异步就是搞赛跑&#xff0c;各显神通&#xff0c;尽最大力量去跑&#xff0c;谁跑得快&#xff0c;…...

【第42天】Arrays.sort 与 Collections.sort 应用 | 整形数组与集合的排序

本文已收录于专栏&#x1f338;《Java入门一百练》&#x1f338;学习指引序、专栏前言一.sort函数二、【例题1】1、题目描述2、解题思路3、模板代码4、代码解析二、【例题1】1、题目描述2、解题思路3、模板代码4、代码解析三、推荐专栏序、专栏前言 本专栏开启&#xff0c;目的…...

LeetCode第334场周赛

2023.2.26LeetCode第334场周赛 A. 左右元素和的差值 思路 前缀和后缀和 代码 class Solution { public:vector<int> leftRigthDifference(vector<int>& nums) {int n nums.size();vector<int> l(n), r(n), ans(n);for (int i 1; i < n; i )l[…...

基于深度学习的三维重建网络PatchMatchNet(三):PatchMatchNet配置及代码主要运行流程

目录 1.PatchMatchNet环境配置 2. PatchMatchNet的大致执行流程(eval.py) 2.1 深度图的保存...

【一天一门编程语言】设计一门编程语言,给出基础语法代码示例,SDK设计。

文章目录设计一门编程语言&#xff0c;给出基础语法代码示例&#xff0c;SDK设计。一、编程语言设计1.1 语言名称1.2 数据类型1.3 基本运算符1.4 控制语句二、SDK设计2.1 基础库2.2 第三方库三、例子用 Mango 这门语言实现斐波那契数列。基础语法代码示例SDK 设计使用 Mango 语…...

ubuntu 下 python 安装 venv

ubuntu 下 python 安装 venv1.首先&#xff0c;确保您的系统已安装 Python3 和 pip3&#xff0c;如果没有安装&#xff0c;可以使用以下命令安装&#xff1a;2. 接着&#xff0c;安装 virtualenv 包&#xff0c;使用以下命令&#xff1a;3.创建 Python 虚拟环境&#xff0c;使用…...

设计模式和设计原则回顾

设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

TDengine 快速体验(Docker 镜像方式)

简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能&#xff0c;本节首先介绍如何通过 Docker 快速体验 TDengine&#xff0c;然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker&#xff0c;请使用 安装包的方式快…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)

2025年能源电力系统与流体力学国际会议&#xff08;EPSFD 2025&#xff09;将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会&#xff0c;EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建

制造业采购供应链管理是企业运营的核心环节&#xff0c;供应链协同管理在供应链上下游企业之间建立紧密的合作关系&#xff0c;通过信息共享、资源整合、业务协同等方式&#xff0c;实现供应链的全面管理和优化&#xff0c;提高供应链的效率和透明度&#xff0c;降低供应链的成…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业

6月9日&#xff0c;国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解&#xff0c;“超级…...

多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验

一、多模态商品数据接口的技术架构 &#xff08;一&#xff09;多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如&#xff0c;当用户上传一张“蓝色连衣裙”的图片时&#xff0c;接口可自动提取图像中的颜色&#xff08;RGB值&…...

蓝桥杯3498 01串的熵

问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798&#xff0c; 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...

用机器学习破解新能源领域的“弃风”难题

音乐发烧友深有体会&#xff0c;玩音乐的本质就是玩电网。火电声音偏暖&#xff0c;水电偏冷&#xff0c;风电偏空旷。至于太阳能发的电&#xff0c;则略显朦胧和单薄。 不知你是否有感觉&#xff0c;近两年家里的音响声音越来越冷&#xff0c;听起来越来越单薄&#xff1f; —…...

水泥厂自动化升级利器:Devicenet转Modbus rtu协议转换网关

在水泥厂的生产流程中&#xff0c;工业自动化网关起着至关重要的作用&#xff0c;尤其是JH-DVN-RTU疆鸿智能Devicenet转Modbus rtu协议转换网关&#xff0c;为水泥厂实现高效生产与精准控制提供了有力支持。 水泥厂设备众多&#xff0c;其中不少设备采用Devicenet协议。Devicen…...

上位机开发过程中的设计模式体会(1):工厂方法模式、单例模式和生成器模式

简介 在我的 QT/C 开发工作中&#xff0c;合理运用设计模式极大地提高了代码的可维护性和可扩展性。本文将分享我在实际项目中应用的三种创造型模式&#xff1a;工厂方法模式、单例模式和生成器模式。 1. 工厂模式 (Factory Pattern) 应用场景 在我的 QT 项目中曾经有一个需…...