golang gin入门

gin是个小而精的web开发框架
官方文档

安装

go get -u github.com/gin-gonic/gin
最简单的起手代码
package mainimport ("net/http""github.com/gin-gonic/gin"
)func main() {r := gin.Default()r.GET("/ping", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"message": "pong",})})r.Run() // listen and serve on 0.0.0.0:8080// r.Run(":8083") // listen and serve on 0.0.0.0:8080
}
get、post、put等http方法
package mainimport ("net/http""github.com/gin-gonic/gin"
)func main() {router := gin.Default()router.GET("/someGet", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"message": "pong",})})router.POST("/somePost", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"message": "pong",})})router.PUT("/somePut", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"message": "pong",})})router.DELETE("/someDelete", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"message": "pong",})})router.PATCH("/somePatch", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"message": "pong",})})router.HEAD("/someHead", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"message": "pong",})})router.OPTIONS("/someOptions", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"message": "pong",})})router.Run() // listen and serve on 0.0.0.0:8080// r.Run(":8083") // listen and serve on 0.0.0.0:8080
}
路由分组
package mainimport ("github.com/gin-gonic/gin"
)func goodList(c *gin.Context) {c.JSON(200, gin.H{"message": "goodList",})
}
func goodsDetail(c *gin.Context) {c.JSON(200, gin.H{"message": "goodsDetail",})
}
func createGoods(c *gin.Context) {c.JSON(200, gin.H{"message": "createGoods",})
}
func main() {router := gin.Default()goodsGroup := router.Group("/goods"){goodsGroup.GET("/list", goodList)goodsGroup.GET("/1", goodsDetail)goodsGroup.GET("/add", createGoods)}router.Run() // listen and serve on 0.0.0.0:8080// r.Run(":8083") // listen and serve on 0.0.0.0:8080
}
带参数的url
package mainimport ("github.com/gin-gonic/gin"
)func goodList(c *gin.Context) {c.JSON(200, gin.H{"message": "goodList",})
}
func goodsDetail(c *gin.Context) {id := c.Param("id")action := c.Param("action")c.JSON(200, gin.H{"message": "goodsDetail","id":      id,"action":  action,})
}
func createGoods(c *gin.Context) {c.JSON(200, gin.H{"message": "createGoods",})
}
func main() {router := gin.Default()goodsGroup := router.Group("/goods"){goodsGroup.GET("", goodList)goodsGroup.GET("/:id/:action", goodsDetail)// goodsGroup.GET("/:id/*action", goodsDetail)goodsGroup.POST("", createGoods)}router.Run() // listen and serve on 0.0.0.0:8080// r.Run(":8083") // listen and serve on 0.0.0.0:8080
}
获取路由分组的参数
package mainimport ("net/http""github.com/gin-gonic/gin"
)type Person struct {ID   string `uri:"id" binding:"required,uuid"`Name string `uri:"name" binding:"required"`
}func main() {router := gin.Default()router.GET("/:name/:id", func(c *gin.Context) {var person Personif err := c.ShouldBindUri(&person); err != nil {c.Status(404)return}c.JSON(http.StatusOK, gin.H{"name": person.Name,"id":   person.ID,})})router.Run() // listen and serve on 0.0.0.0:8080// r.Run(":8083") // listen and serve on 0.0.0.0:8080
}

http://localhost:8080/sd1/8bebdad9-2829-4849-a011-c19128061822

获取get和post参数

get、post和get&post

package mainimport ("fmt""net/http""github.com/gin-gonic/gin"
)func welcome(c *gin.Context) {firstName := c.DefaultQuery("firstname", "bobby")lastName := c.Query("lastname")c.JSON(http.StatusOK, gin.H{"first_name": firstName,"last_name":  lastName,})
}func formPost(c *gin.Context) {message := c.PostForm("message")nick := c.DefaultPostForm("nick", "anonymous")c.JSON(http.StatusOK, gin.H{"message": message,"nick":    nick,})
}func main() {router := gin.Default()//get请求router.GET("/welcome", welcome)//post请求router.POST("/form", formPost)//post & getrouter.POST("/postsd", func(c *gin.Context) {id := c.Query("id")page := c.DefaultQuery("page", "0")name := c.PostForm("name")message := c.PostForm("message")fmt.Printf("id: %s,page: %s,name: %s,message: %s", id, page, name, message)})router.Run() // listen and serve on 0.0.0.0:8080// r.Run(":8083") // listen and serve on 0.0.0.0:8080
}

在这里插入图片描述

http://localhost:8080/welcome?firstname=dlkjf&lastname=sdfljk

JSON、ProtoBuf 渲染

json渲染、Prootobuf渲染和purejson渲染

package mainimport ("net/http""GolangStudy/Introduction/proto""github.com/gin-gonic/gin"
)func moreJSON(c *gin.Context) {var msg struct {Name    string `json:"user"`Message stringNumber  int}msg.Name = "bobby"msg.Message = "测试json"msg.Number = 20c.JSON(http.StatusOK, msg)
}
func returnProto(c *gin.Context) {user := &proto.Teacher{Name:   "bobby",Course: []string{"python", "go", "java"},}c.ProtoBuf(http.StatusOK, user)
}
func main() {router := gin.Default()router.GET("/moreJSON", moreJSON)router.GET("/someProtoBuf", returnProto)router.GET("/pureJSON", func(c *gin.Context) {c.PureJSON(200, gin.H{"html": "<b>Hello, world!</b>",})})router.Run()
}
表单验证

Gin使用 go-playground/validator 验证参数
文档

package mainimport ("fmt""net/http""github.com/gin-gonic/gin"
)// 绑定为json
type LoginForm struct {User     string `form:"user" json:"user" xml:"user"  binding:"required,min=3,max=10"` //min最短长度,max最大长度Password string `form:"password" json:"password" xml:"password" binding:"required"`
}func main() {router := gin.Default()router.POST("/loginJSON", func(c *gin.Context) {var loginForm LoginFormif err := c.ShouldBind(&loginForm); err != nil {fmt.Println(err.Error())c.JSON(http.StatusBadRequest, gin.H{"error": err.Error(),})return}c.JSON(http.StatusOK, gin.H{"msg": "登录成功",})})router.Run()
}

在这里插入图片描述

注册表单的验证
package mainimport ("fmt""net/http""github.com/gin-gonic/gin"
)// 绑定为json
type LoginForm struct {User     string `form:"user" json:"user" xml:"user"  binding:"required,min=3,max=10"` //min最短长度,max最大长度Password string `form:"password" json:"password" xml:"password" binding:"required"`
}type SignUpForm struct {Age        uint8  `json:"age" binding:"gte=1,lte=130"`Name       string `json:"name" binding:"required,min=3"`Email      string `json:"email" binding:"required,email"`Password   string `json:"password" binding:"required"`RePassword string `json:"re_password" binding:"required,eqfield=Password"`
}func main() {router := gin.Default()router.POST("/loginJSON", func(c *gin.Context) {var loginForm LoginFormif err := c.ShouldBind(&loginForm); err != nil {fmt.Println(err.Error())c.JSON(http.StatusBadRequest, gin.H{"error": err.Error(),})return}c.JSON(http.StatusOK, gin.H{"msg": "登录成功",})})router.POST("/signup", func(c *gin.Context) {var signForm SignUpFormif err := c.ShouldBind(&signForm); err != nil {fmt.Println(err.Error())c.JSON(http.StatusBadRequest, gin.H{"error": err.Error(),})return}c.JSON(http.StatusBadRequest, gin.H{"msg": "注册成功",})})router.Run()
}

在这里插入图片描述

表单验证错误翻译成中文
package mainimport ("fmt""net/http""reflect""strings""github.com/gin-gonic/gin""github.com/gin-gonic/gin/binding""github.com/go-playground/locales/en""github.com/go-playground/locales/zh"ut "github.com/go-playground/universal-translator""github.com/go-playground/validator/v10"en_translations "github.com/go-playground/validator/v10/translations/en"zh_translations "github.com/go-playground/validator/v10/translations/zh"
)// 绑定为json
type LoginForm struct {User     string `form:"user" json:"user" xml:"user"  binding:"required,min=3,max=10"` //min最短长度,max最大长度Password string `form:"password" json:"password" xml:"password" binding:"required"`
}type SignUpForm struct {Age        uint8  `json:"age" binding:"gte=1,lte=130"`Name       string `json:"name" binding:"required,min=3"`Email      string `json:"email" binding:"required,email"`Password   string `json:"password" binding:"required"`RePassword string `json:"re_password" binding:"required,eqfield=Password"`
}func removeTopStruct(fileds map[string]string) map[string]string {rsp := map[string]string{}for field, err := range fileds {rsp[field[strings.Index(field, ".")+1:]] = err}return rsp
}
func InitTrans(locale string) (err error) {//修改gin的validator引擎属性,实现定制if v, ok := binding.Validator.Engine().(*validator.Validate); ok {//注册一个获取json的tag的自定义方法v.RegisterTagNameFunc(func(fld reflect.StructField) string {name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]if name == "-" {return ""}return name})zhT := zh.New() //中文翻译器enT := en.New() //英文翻译器//第一个是备用的,后面的是支持的语言环境uni := ut.New(enT, zhT, enT)trans, ok = uni.GetTranslator(locale)if !ok {return fmt.Errorf("uni.GetTranslator(%s)", locale)}switch locale {case "en":en_translations.RegisterDefaultTranslations(v, trans)case "zh":zh_translations.RegisterDefaultTranslations(v, trans)default:en_translations.RegisterDefaultTranslations(v, trans)}return}return
}var trans ut.Translatorfunc main() {if err := InitTrans("zh"); err != nil {fmt.Println("初始化翻译器错误")return}router := gin.Default()router.POST("/loginJSON", func(c *gin.Context) {var loginForm LoginFormif err := c.ShouldBind(&loginForm); err != nil {errs, ok := err.(validator.ValidationErrors)if !ok {c.JSON(http.StatusOK, gin.H{"msg": err.Error(),})} else {c.JSON(http.StatusBadRequest, gin.H{"error": removeTopStruct(errs.Translate(trans)),})}fmt.Println(err.Error())return}c.JSON(http.StatusOK, gin.H{"msg": "登录成功",})})router.POST("/signup", func(c *gin.Context) {var signForm SignUpFormif err := c.ShouldBind(&signForm); err != nil {errs, ok := err.(validator.ValidationErrors)if !ok {c.JSON(http.StatusOK, gin.H{"msg": err.Error(),})} else {c.JSON(http.StatusBadRequest, gin.H{"error": removeTopStruct(errs.Translate(trans)),})}fmt.Println(err.Error())return}c.JSON(http.StatusBadRequest, gin.H{"msg": "注册成功",})})router.Run()
}

在这里插入图片描述

中间件

gin.New()可以添加中间件;gin.Default()默认启动方式,包含 Logger、Recovery 中间件
添加中间件

package mainimport ("fmt""net/http""time""github.com/gin-gonic/gin"
)func MyLogger() gin.HandlerFunc {return func(c *gin.Context) {t := time.Now()c.Set("example", "123456")//让原本该执行的逻辑继续执行c.Next()end := time.Since(t)fmt.Printf("耗时:%V\n", end)status := c.Writer.Status()fmt.Println("状态", status)}
}
func main() {router := gin.New()//使用logger和recovery中间件router.Use(MyLogger())router.GET("/ping", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"message": "pong",})})router.Run()
}

通过c.abort()实现中止中间件的执行(通过return是不能终止的,因为中间件都存储在中间件队列中,当前中间的中止会继续调用后续的中间件,直到调用完成。c.abort()会将中间件队列的索引值改为math.MaxInt8/2实现不调用后续中间件)

package mainimport ("fmt""net/http""time""github.com/gin-gonic/gin"
)func MyLogger() gin.HandlerFunc {return func(c *gin.Context) {t := time.Now()c.Set("example", "123456")//让原本该执行的逻辑继续执行c.Next()end := time.Since(t)fmt.Printf("耗时:%V\n", end)status := c.Writer.Status()fmt.Println("状态", status)}
}
func TokenRequired() gin.HandlerFunc {return func(c *gin.Context) {var token stringfor k, v := range c.Request.Header {if k == "X-Token" {token = v[0]}fmt.Println(k, v, token)}if token != "bobby" {c.JSON(http.StatusUnauthorized, gin.H{"msg": "未登录",})c.Abort()}c.Next()}
}
func main() {router := gin.New()//使用logger和recovery中间件router.Use(TokenRequired())router.GET("/ping", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"message": "pong",})})router.Run()
}
gin加载html文件

在这里插入图片描述
html路径可以使用绝对路径和相对路径(推荐),使用相对路径需要先go build后运行,主要是因为直接通过编译器执行生成的可执行文件放置于系统的临时文件夹中并不抱存在当前项目的路径下,所以会出现找不到html文件。

package mainimport ("net/http""github.com/gin-gonic/gin"
)func main() {router := gin.Default()//制定加载好相对路径router.LoadHTMLFiles("templates/index.tmpl")router.GET("/index", func(c *gin.Context) {c.HTML(http.StatusOK, "index.tmpl", gin.H{"title": "mooc",})})router.Run()
}

加载多html文件

package mainimport ("net/http""github.com/gin-gonic/gin"
)func main() {router := gin.Default()//制定加载好相对路径//加载二级目录router.LoadHTMLGlob("templates/**/*")// router.LoadHTMLFiles("templates/index.tmpl", "templates/goods.html")router.GET("/index", func(c *gin.Context) {c.HTML(http.StatusOK, "index.tmpl", gin.H{"title": "mooc",})})router.GET("/goods/list", func(c *gin.Context) {c.HTML(http.StatusOK, "goods/list.html", gin.H{"name": "微服务开发",})})router.GET("/users/list", func(c *gin.Context) {c.HTML(http.StatusOK, "users/list.html", gin.H{"name": "微服务开发",})})router.Run()
}
优雅退出

自定义监听结束信号,方便完成关闭服务器等后续操作

package mainimport ("fmt""net/http""os""os/signal""syscall""github.com/gin-gonic/gin"
)func main() {//优雅推出,当我们关闭程序后需要做的处理//微服务 启动之前或者启动之后必须做一件事:将当前的ip地址和端口号注册到注册中心//我们当前的服务停止之后并没有告知注册中心router := gin.Default()router.GET("/", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"msg": "pong",})})go func() {router.Run()}()//接受信号quit := make(chan os.Signal)//syscall.SIGINT ctrl+csignal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)<-quit//处理后续的逻辑fmt.Println("关闭server中。。。")fmt.Println("注册服务。。。")
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1556097.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Java IO流全面教程

此笔记来自于B站黑马程序员 File 创建对象 public class FileTest1 {public static void main(String[] args) {// 1.创建一个 File 对象&#xff0c;指代某个具体的文件// 路径分隔符// File f1 new File("D:/resource/ab.txt");// File f1 new FIle("D:\\…

nodejs 构建高性能服务器的关键技术

nodejs 构建高性能服务器的关键技术 演示地址 演示地址 源码地址 源码地址 获取更多 获取更多 在现代 Web 开发中&#xff0c;Node.js 已成为构建高性能、可扩展网络应用的首选平台之一。它的非阻塞 I/O 模型与事件驱动架构使其能够在处理大量并发请求时表现出色&#xff0…

【C++11】新特性

前言&#xff1a; C11 是C编程语言的一个重要版本&#xff0c;于2011年发布。它带来了数量可观的变化&#xff0c;包含约 140 个新特性&#xff0c;以及对 C03 标准中约600个缺陷的修正&#xff0c;更像是从 C98/03 中孕育出的新语言 列表初始化 C11 中的列表初始化&#xff0…

【自用】王道文件管理强化笔记

文章目录 操作系统引导:磁盘初始化文件打开过程角度1文件的打开过程角度2 内存映射的文件访问 操作系统引导: ①CPU从一个特定主存地址开始&#xff0c;取指令&#xff0c;执行ROM中的引导程序(先进行硬件自检&#xff0c;再开机) ②)将磁盘的第一块–主引导记录读入内存&…

谷粒商城のRabbitMQ基础篇

文章目录 前言一、Rabbit MQ简介1、基本概念2、组件架构 二、使用步骤1.引入依赖2.application.properties3、docker 安装Rabbit MQ3、使用案例3.1、定义队列3.2、定义交换机3.3、绑定3.4、发送消息3.5、接受消息3.5、自定义消息序列化方式3.6、演示Fanout 交换机模式3.7、演示…

Vue基础(二)

计算属性与监视姓名案例 插值语法实现 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>姓名案例&l…

用人工智能写作:专业作家利用 ChatGPT 的五种方式 ✍️

用人工智能写作&#xff1a;专业作家利用 ChatGPT 的五种方式 &#x1f3a8;✍️ 在写作领域&#xff0c;人工智能工具如 ChatGPT 正逐渐成为作家们的得力助手。它不仅帮助优化文本&#xff0c;还能激发灵感、完善叙事结构&#xff0c;甚至推动创新。本文将通过五个具体案例&a…

【微服务】服务注册与发现 - Eureka(day3)

CAP理论 P是分区容错性。简单来说&#xff0c;分区容错性表示分布式服务中一个节点挂掉了&#xff0c;并不影响其他节点对外提供服务。也就是一台服务器出错了&#xff0c;仍然可以对外进行响应&#xff0c;不会因为某一台服务器出错而导致所有的请求都无法响应。综上所述&…

实验4 循环结构

1、判断素数 【问题描述】从键盘输入一个大于1的正整数&#xff0c;判断是否为素数 【输入形式】输入一个正整数 【输出形式】输出该数是否为素数 【样例输入】10 【样例输出】10 is not a prime number 【样例说明】样例2 输入&#xff1a;-10 输出&#xff1a;error! #de…

jmeter学习(7)beanshell

beanshell preprocessor 发送请求前执行 beanshell postprocessor 发送请求前执行 获取请求相关信息 String body sampler.getArguments().getArgument(0).getValue(); String url sampler.getPath(); 获取响应报文 String responseprev.getResponseDataAsString(); 获…

北京自闭症寄宿学校大盘点:优质教育资源汇总

北京自闭症寄宿学校大盘点&#xff1a;优质教育资源中的璀璨明珠——兼谈广州星贝育园 在北京&#xff0c;随着社会对自闭症儿童教育的日益重视&#xff0c;越来越多的优质寄宿学校应运而生&#xff0c;为这些特殊的孩子提供了专业的康复与教育环境。然而&#xff0c;当我们把…

【数据结构】【链表代码】随机链表的复制

/*** Definition for a Node.* struct Node {* int val;* struct Node *next;* struct Node *random;* };*/typedef struct Node Node; struct Node* copyRandomList(struct Node* head) {if(headNULL)return NULL;//1.拷贝结点&#xff0c;连接到原结点的后面Node…

猫头虎深度解读:过去2周,AI领域的十大突破事件与未来展望

猫头虎深度解读&#xff1a;过去2周&#xff0c;AI领域的十大突破事件与未来展望 &#x1f680;&#x1f916; 大家好&#xff0c;我是猫头虎技术团队的代表&#xff01;这两周&#xff0c;人工智能领域再次掀起了技术与应用的新浪潮。从立法到技术进展&#xff0c;再到前沿应…

初始爬虫12(反爬与反反爬)

学到这里&#xff0c;已经可以开始实战项目了&#xff0c;多去爬虫&#xff0c;了解熟悉反爬&#xff0c;然后自己总结出一套方法怎么做。 1.服务器反爬的原因 服务器反爬的原因 总结&#xff1a; 1.爬虫占总PV较高&#xff0c;浪费资源 2.资源被批量抓走&#xff0c;丧失竞争力…

交叉熵的数学推导和手撕代码

交叉熵的数学推导和手撕代码 数学推导手撕代码 数学推导 手撕代码 import torch import torch.nn.functional as F# 二元交叉熵损失函数 def binary_cross_entropy(predictions, targets):# predictions应为sigmoid函数的输出&#xff0c;即概率值# targets应为0或1的二进制标…

MathType软件7.7最新版本下载安装教程+使用深度评测

嘿&#xff0c;各位亲爱的朋友们&#xff01;&#x1f44b; 今天我要来给大家安利一个神器——MathType软件&#xff01;&#x1f389; 如果你是一位学生、老师或者需要经常和数学公式打交道的科研工作者&#xff0c;那这个软件绝对是你的不二选择&#xff01;&#x1f60e; M…

ctf.bugku-备份是个好习惯

访问页面得到字符串 这串字符串是重复的&#xff1b; d41d8cd98f00b204e9800998ecf8427e 从前端、源码上看&#xff0c;除了这段字符串&#xff0c;没有其他信息&#xff1b;尝试解密&#xff0c;长度32位&#xff1b;各种解密方式试试&#xff1b; MD5免费在线解密破解_MD5在…

市面上8款AI论文大纲一键生成文献的软件推荐

在当前的学术研究和写作领域&#xff0c;AI论文大纲自动生成软件已经成为提高写作效率和质量的重要工具。这些工具不仅能够帮助研究人员快速生成论文草稿&#xff0c;还能进行内容优化、查重和排版等操作。本文将分享市面上8款AI论文大纲一键生成文献的软件&#xff0c;并特别推…

[git] github管理项目之环境依赖管理

导出依赖到 requirements.txt pip install pipreqs pipreqs . --encodingutf8 --force但是直接使用pip安装不了torch&#xff0c;需要添加源&#xff01;&#xff01; pip install -r requirements.txt -f https://download.pytorch.org/whl/torch_stable.htmlpython 项目中 …

Stable Diffusion绘画 | AI 图片智能扩充,超越PS扩图的AI扩图功能(附安装包)

来到「文生图」页面&#xff0c;输入固定的起手式提示词。 第1步&#xff0c;开启 ControlNet&#xff0c;将需要扩充的图片加载进来&#xff1a; 控制类型选择「Inpaint」&#xff0c;预处理器选择「inpaint_onlylama」&#xff0c;缩放模式选择「缩放后填充空白」&#xff1…