【Go】Go Gin框架初识(一)

1. 什么是Gin框架

Gin框架:是一个由 Golang 语言开发的 web 框架,能够极大提高开发 web 应用的效率!

1.1 什么是web框架

web框架体系图(前后端不分离)如下图所示:

从上图中我们可以发现一个Web框架最重要的一些组成部分:

  • HTTP解析/封装系统:解析HTTP请求以及将响应构造为HTTP请求等任务交由web框架来完成
  • 路由系统:将一个请求路由给某一个指定的处理器函数
  • 逻辑处理系统:是后端人员需要关注的重点区域,编写具体业务逻辑以及链接数据库
  • 模板引擎(前后端不分离):将数据嵌入到HTML模板中,构建动态页面

简单来说,web框架将一些繁琐且与业务逻辑无关的部分封装起来供开发者使用,这样开发人员只需要关注业务逻辑层的实现

1.2 web框架两种架构模式

常见的 web 架构模式有两种:

  1. 前后端不分离
  2. 前后端分离

上面已经介绍了前后端不分离的架构体系图,下图是前后端分离的架构图:

可以看出主要区别在于后端没有了模板引擎,意味着HTML页面、图片等static静态资源全部都在前端服务器部署(如nginx),后端服务器只负责编写接口进行业务逻辑处理,然后将前端所需的数据暴露成接口返回!(不和页面打任何交道)

2. Gin框架

2.1 Gin框架如何安装

在Go 1.11之后引入了包管理机制,我们就可以使用go mod tidy一键将代码中所需导入的包从远程服务器下载到本地

go 复制代码
package main

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

func main() {
    // 获取引擎对象
    r := gin.Default()
    // 设置路由
    r.GET("/hello", func(c *gin.Context) {
        c.String(200, "Hello Gin")
    })
    // 启动
    r.Run(":8080")
}

编写完上述代码以后在控制台输入以下命令:

  1. go mod init gin_first:包管理初始化
  2. go mod tidy:下载所需依赖

看到上述信息就表明 gin 框架已经引入完毕!可以正式编写代码啦~

2.2 Gin框架的路由系统

2.2.1 基本使用

其实在 2.1 节我们已经初步使用过路由系统了

go 复制代码
// 设置路由
r.GET("/hello", func(c *gin.Context) {
    c.String(200, "hello gin")
})

基本语法:r.操作方法(url, 处理器函数)

  • 操作方法:引擎对象基本支持所有的HTTP请求方法,比如GET、POST、PUT、PATCH、DELETE、HEAD、OPTIONS,以及Any(任何请求)、NoRoute(没有请求对应上时访问)
  • url:表示请求对应的路径
  • 处理器函数:表示请求路径为"/hello"时映射到该处理器函数进行执行

现在我们通过浏览器使用GET请求访问路径:http://localhost:8080/hello

2.2.2 路由分组

有时候我们希望对一个 url 路径做更统一化的管理,比如"/user/login"和"/user/register"实际上都是在"/user"路径下的子路由,这个时候就需要引入 路由分组

基本语法:子路由对象 := r.Group(根路由)

go 复制代码
package main

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

func main() {
	// 获取引擎对象
	r := gin.Default()
	// 设置根路由
	userRouter := r.Group("/user")
	{
		userRouter.GET("/login", func(ctx *gin.Context) {
			ctx.String(200, "/user/login")
		})
		userRouter.GET("/register", func(ctx *gin.Context) {
			ctx.String(200, "/user/register")
		})
	}
	// 启动
	r.Run(":8080")
}

2.3 Gin框架获取参数

2.3.1 获取基本信息
2.3.1.1 获取请求方法

比如在Any请求内部想要知道具体请求方法可以使用:

基本语法:var method string = ctx.Request.Method

go 复制代码
package main

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

func handleFunc(ctx *gin.Context) {
	// 获取请求方法
	method := ctx.Request.Method
	fmt.Println("请求方法是:" + method)
	ctx.String(200, "request ok")
}

func main() {
	// 获取引擎对象
	r := gin.Default()
	// 设置路由
	r.Any("/method", handleFunc)
	// 启动
	r.Run(":8080")
}

代码运行结果:

2.3.1.2 获取请求URL

基本语法:var url string = ctx.Request.URL

go 复制代码
package main

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

func handleFunc(ctx *gin.Context) {
	// 获取请求URL
	var url string = ctx.Request.URL.String()
	fmt.Println("请求URL是:" + url)
	ctx.String(200, "request ok")
}

func main() {
	// 获取引擎对象
	r := gin.Default()
	// 设置路由
	r.GET("/url", handleFunc)
	// 启动
	r.Run(":8080")
}

代码运行结果:

2.3.1.3 获取远程IP地址

基本语法:

  • 方式一:var remoteAddr string = ctx.Request.RemoteAddr(包含端口)
  • 方式二:var remoteAddr string = ctx.ClientIP()(不包含端口)
go 复制代码
package main

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

func handleFunc1(ctx *gin.Context) {
	// 获取远程ip
	var addr string = ctx.Request.RemoteAddr
	fmt.Println("远程ip:", addr)
	ctx.String(200, "request ok")
}

func handleFunc2(ctx *gin.Context) {
	// 获取远程ip
	var addr string = ctx.ClientIP()
	fmt.Println("远程ip:", addr)
	ctx.String(200, "request ok")
}

func main() {
	// 获取引擎对象
	r := gin.Default()
	// 设置路由
	r.GET("/addr1", handleFunc1)
	r.GET("/addr2", handleFunc2)
	// 启动
	r.Run(":8080")
}

代码运行结果:

2.3.1.4 获取请求头信息

本语法:var headerInfo string = ctx.GetHeader(键)

go 复制代码
package main

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

func handleFunc(ctx *gin.Context) {
	// 获取指定请求头
	var userAgent string = ctx.GetHeader("User-Agent")
	fmt.Println("Content-Type:", userAgent)
	ctx.String(200, "request ok")
}

func main() {
	// 获取引擎对象
	r := gin.Default()
	// 设置路由
	r.GET("/header", handleFunc)
	// 启动
	r.Run(":8080")
}

代码运行结果:

2.3.2 获取请求数据
2.3.2.1 获取查询字符串内容

通常来说使用 GET 请求发送请求都会将数据放置在查询字符串位置

  • 方式一 :var content string = ctx.Query(键)
  • 方式二:var content string = ctx.DefaultQuery(键, 缺省值),如果不存在则使用默认值填充
  • 方式三:value, ok := ctx.GetQuery(键),可以通过ok判断是否存在键
go 复制代码
package main

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

func handleFunc1(ctx *gin.Context) {
	// 获取查询字符串数据
	var username = ctx.Query("username")
	var pwd = ctx.Query("pwd")
	fmt.Println("username:", username)
	fmt.Println("pwd:", pwd)
	ctx.String(200, "request ok")
}

func handleFunc2(ctx *gin.Context) {
	// 获取查询字符串数据
	var user = ctx.DefaultQuery("user", "wjj")
	fmt.Println("user:", user)
	ctx.String(200, "request ok")
}

func handleFunc3(ctx *gin.Context) {
	// 获取查询字符串数据
	user, exists := ctx.GetQuery("user")
	if exists {
		fmt.Println("键存在,值为:", user)
	} else {
		fmt.Println("键不存在!")
	}
	ctx.String(200, "request ok")
}

func main() {
	// 获取引擎对象
	r := gin.Default()
	// 设置路由
	r.GET("/queryString1", handleFunc1)
	r.GET("/queryString2", handleFunc2)
	r.GET("/queryString3", handleFunc3)
	// 启动
	r.Run(":8080")
}

程序运行结果:

2.3.2.2 获取表单数据

前端使用 form表单 提交发送请求,此时Content-Typex-www-form-urlencoded可以使用PostForm获取表单内容

  • 方式一 :var content string = ctx.PostForm(键)
  • 方式二:var content string = ctx.DefaultPostForm(键, 缺省值),如果不存在则使用默认值填充
  • 方式三:value, ok := ctx.GetPostForm(键),可以通过ok判断是否存在键
go 复制代码
package main

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

func handleFunc1(ctx *gin.Context) {
	// 获取查询字符串数据
	var username = ctx.PostForm("username")
	var pwd = ctx.PostForm("pwd")
	fmt.Println("username:", username)
	fmt.Println("pwd:", pwd)
	ctx.String(200, "request ok")
}

func handleFunc2(ctx *gin.Context) {
	// 获取查询字符串数据
	var user = ctx.DefaultPostForm("user", "wjj")
	fmt.Println("user:", user)
	ctx.String(200, "request ok")
}

func handleFunc3(ctx *gin.Context) {
	// 获取查询字符串数据
	user, exists := ctx.GetPostForm("user")
	if exists {
		fmt.Println("键存在,值为:", user)
	} else {
		fmt.Println("键不存在!")
	}
	ctx.String(200, "request ok")
}

func main() {
	// 获取引擎对象
	r := gin.Default()
	// 加载HTML资源
	r.LoadHTMLGlob("templates/*")
	// 设置路由
	r.GET("/", func(ctx *gin.Context) {
		ctx.HTML(200, "index.html", nil)
	})
	r.POST("/postform1", handleFunc1)
	r.POST("/postform2", handleFunc2)
	r.POST("/postform3", handleFunc3)
	// 启动
	r.Run(":8080")
}

程序运行结果:

2.3.2.3 获取JSON请求体数据

Go语言没有提供类似于 PostForm、Query 这样的API直接获取JSON数据,但是Go提供了ShouldBind函数,可以将 json 类型的数据自动映射到指定的结构体对象上

语法格式:ctx.ShouldBind(&结构体对象)

go 复制代码
package main

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

type Student struct {
	Username string `json:"username"`
	Password string `json:"password"`
}

func main() {
	// 获取引擎对象
	r := gin.Default()
	// 设置路由
	r.POST("/", func(ctx *gin.Context) {
		// 使用ShouldBind函数获取JSON数据
		var student Student
		err := ctx.ShouldBind(&student)
		if err != nil {
			fmt.Println(err)
			ctx.String(500, "解析错误")
		} else {
			fmt.Println(student)
			ctx.String(200, "request ok")
		}
	})
	// 启动
	r.Run(":8080")
}

程序运行结果:

2.4 Gin框架返回响应

2.4.1 返回HTML页面

语法格式:ctx.HTML(响应状态码, 页面, 数据对象)

  • 响应状态码:对应的HTTP状态码
  • 页面:具体页面路径
  • 数据对象:与模板引擎相关(后续章节介绍)
go 复制代码
package main

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

func main() {
	// 获取引擎对象
	r := gin.Default()
	// 加载模板文件
	r.LoadHTMLGlob("templates/*")
	// 设置路由
	r.GET("/", func(ctx *gin.Context) {
		// 返回首页
		ctx.HTML(202, "index.html", nil)
	})
	// 启动
	r.Run(":8080")
}

程序运行结果:

2.4.2 返回String类型

语法格式:ctx.String(响应状态码, 格式化字符串)

  • 响应状态码:对应的HTTP状态码
  • 格式化字符串:具体返回的文本内容
go 复制代码
package main

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

func main() {
	// 获取引擎对象
	r := gin.Default()
	// 设置路由
	r.GET("/", func(ctx *gin.Context) {
		// 返回sring类型
		ctx.String(200, "string 类型")
	})
	// 启动
	r.Run(":8080")
}

程序运行结果:

2.4.3 返回JSON类型

语法格式:ctx.JSON(响应状态码, gin.H对象)

  • 响应状态码:对应的HTTP状态码
  • gin.H对象:具体返回JSON格式对象
go 复制代码
package main

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

func main() {
	// 获取引擎对象
	r := gin.Default()
	// 设置路由
	r.GET("/", func(ctx *gin.Context) {
		// 返回json类型
		ctx.JSON(200, gin.H{
			"name": "wjj",
			"age":  21,
		})
	})
	// 启动
	r.Run(":8080")
}

程序运行结果:

2.4.4 返回XML类型

语法格式:ctx.XML(响应状态码, gin.H对象)

  • 响应状态码:对应的HTTP状态码
  • gin.H对象:具体返回XML格式对象
go 复制代码
package main

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

func main() {
	// 获取引擎对象
	r := gin.Default()
	// 设置路由
	r.GET("/", func(ctx *gin.Context) {
		ctx.XML(200, gin.H{
			"name": "wjj",
			"age":  21,
		})
	})
	// 启动
	r.Run(":8080")
}

程序运行结果:

相关推荐
福大大架构师每日一题14 小时前
ollama v0.30.7 正式发布:Hermes 桌面端落地,接口、文档、底层依赖全方位优化
golang·log4j
不爱编程的小陈16 小时前
深入解析 Go 网络 I/O 的底层引擎:从 epoll 到 netpoll
服务器·网络·golang
何以解忧,唯有..20 小时前
Go 语言数据类型详解:从基础到复合类型
开发语言·golang·mfc
踏着七彩祥云的小丑20 小时前
Go学习第7天:Map集合 + 递归函数 + 类型转换
开发语言·学习·golang·go
何以解忧,唯有..20 小时前
Go语言变量的声明方式详解
开发语言·后端·golang
寂夜了无痕21 小时前
Go 多版本管理工具G 保姆级安装配置教程
golang·go多版本管理
张忠琳21 小时前
【Go 1.26.4】Golang Slice 深度解析
开发语言·后端·golang
张忠琳1 天前
【Go 1.26.4】Golang Channel 深度解析
开发语言·后端·golang
张忠琳2 天前
【Go 1.26.4】Golang Map 深度解析
开发语言·后端·golang
何以解忧,唯有..2 天前
Go 语言安装与环境配置完整指南
开发语言·后端·golang