[GO]读取好友列表为例,解析gin框架的工作流程

概要

gin框架是一个轻量级的web框架,用于快速构建高性能的RESTful API服务。它基于Go语言,并封装了多种功能,例如路由、中间件、JSON解析、表单解析、参数绑定、验证等。
gorm是一个开源的ORM(Object-relational mapping)库,它可以用来操作各种数据库,如MySQL、PostgreSQL、SQLite等。它提供了简单易用的API,可以帮助开发人员快速高效地操作数据库。
本文会以读取好友列表为例,解析gin框架和gorm工具的工作流程

整体架构流程

1、先router设置对应接口,连接到service
2、在service获取用户参数,格式化数据调用models(工具模块)查询数据
3、在models层调用gorm查询数据并返回service
4、响应结果

函数入口——main()

func main() {
	utils.InitConfig()
	utils.InitMySQL()
	utils.InitRedis()
	r := router.Router()
	r.Run(":8081") // 监听并在 0.0.0.0:8081 上启动服务
}

前三行初始化数据库和配置:略
我们从第四行router开始讲

router函数解释——router.Router()

//router模块中的Router函数
func Router() *gin.Engine {
	r := gin.Default()
	//获取好友关系
	...//表示中间略过其他内容
	r.POST("/searchFriends", service.SearchFriends)
	return r
}

函数返回值——*gin.Engine

*gin.Engine是Gin框架的核心结构之一,它是HTTP路由处理器中间件的集合。在Gin中,我们可以通过gin.New()函数创建一个Engine实例,然后通过调用Engine实例的方法来定义路由和中间件,以处理客户端请求。

以下是*gin.Engine中的一些主要方法:

  1. Use()方法:用于注册全局中间件,作用于所有定义的路由。

  2. GET()、POST()、PUT()、DELETE()等方法:用于处理不同的HTTP请求方法,并指定对应的处理器函数或处理器链。

  3. Group()方法:用于将一组路由和中间件打包起来,以便统一管理和配置。

  4. Static()方法:用于注册静态文件路由。

  5. Handle()方法:用于注册自定义路由。

  6. Any()方法:用于注册任意HTTP请求方法的路由。

  7. Redirect()方法:用于注册重定向路由。

  8. NoRoute()方法:用于定义当没有路由匹配请求时的处理函数。

通过这些方法,我们可以灵活地定义Gin应用程序的路由和中间件,以实现各种需求。

函数解释——gin.Default()

gin源码

// Default returns an Engine instance with the Logger and Recovery middleware already attached.
func Default() *Engine {
	debugPrintWARNINGDefault()
	engine := New()
	engine.Use(Logger(), Recovery())
	return engine
}

其中,Default方法是Gin框架的一个核心方法。

默认情况下,Gin会使用Default方法创建一个名为“engine”的实例。该实例是Gin应用程序中HTTP请求的主要路由器。在Gin应用程序中,可以通过engine变量来访问该实例。

Default方法具有以下特点:

  1. 该方法是一个全局函数,可以在任何地方调用,不需要显式地创建一个实例。

  2. 该方法返回一个指向Gin框架的engine实例的指针。

  3. 如果已经调用了Default方法,则再次调用不会创建一个新的实例,而是返回先前创建的实例。

实际运行

1、使用postman像服务器发送访问请求
用
2、当URL正确时,会准确路由到service的函数
(PS:router.Router()用于实例化,所以对服务器的请求不会运行到router模块)
在这里插入图片描述

service层

service函数一般流程:
1、需要接收要使用的参数参数
2、逻辑处理
3、操作数据库
4、返回结果

返回值——*gin.Context

*gin.Context 是 Gin Web 框架中的一个重要结构体,它包含了一个 HTTP 请求的所有信息和操作函数,可以让我们在处理请求时方便地获取请求参数、设置响应信息等。

具体来说,*gin.Context 可以提供以下功能:

  1. 获取请求参数:通过 *gin.Context 中的 `Query、QueryArray、PostForm、DefaultPostForm 等函数,我们可以获取请求中的参数。

  2. 设置响应信息:通过 *gin.Context 中的 JSON、XML、YAML、HTML、String 等函数,我们可以设置响应的格式和内容。

  3. 设置响应状态码:通过 *gin.Context 中的 Status 函数,我们可以设置响应的状态码。

  4. 跳转页面:通过 *gin.Context 中的 Redirect 函数,我们可以实现页面之间的跳转。

  5. 获取请求头信息:通过 *gin.Context 中的 Request 变量,我们可以获取请求头信息,例如 User-Agent、Referer 等。

总之,*gin.Context 可以让我们方便地处理 HTTP 请求和响应,实现 Web 应用程序的功能。

获取参数——以post为例

c.Request.FormValue() 是 Gin 框架中的一个函数,用于获取请求表单中指定键名(key)对应的值(value)。

c.Request 是指 HTTP 请求上下文对象,包含了许多关于当前请求的信息,包括请求方法、URL、请求头部、请求体(body)等。

当客户端发送 POST 或 PUT 请求时,请求表单中可能包含了多个参数(key-value 对),例如,用户名、密码、邮件地址等等。使用 c.Request.FormValue() 可以轻松地获取到指定键名(key)对应的值(value)。

使用方法如下:

value := c.Request.FormValue("key")

其中,“key” 表示请求表单中的参数名,函数返回值为一个字符串类型的参数值(value)。如果不存在对应的参数名,则函数返回空字符串""。

在数据库查询id的好友列表——models.SearchFriend(id)

// 返回userId用户的好友列表
func SearchFriend(userId uint) []UserBasic {
	contacts := make([]Contact, 0)
	objIds := make([]uint64, 0)
	//先获取userId的每一条好友关系(Contact)
	utils.DB.Where("owner_id = ? and type = 1", userId).Find(&contacts)
	//然后遍历添加好友ID到objIds
	for _, v := range contacts {
		fmt.Println(v)
		objIds = append(objIds, uint64(v.TargetId))
	}
	users := make([]UserBasic, 0)
	//查询好友ID并返回
	utils.DB.Where("id in ?", objIds).Find(&users)
	return users
}

查询逻辑

1、获取userId的每一条好友关系(Contact)
2、遍历添加好友ID到objIds
3、查询好友ID并返回

utils.DB 介绍

DB原名
package utils
var DB *gorm.DB
gorm定义DB源码

// DB GORM DB definition
type DB struct {
	*Config
	Error        error
	RowsAffected int64
	Statement    *Statement
	clone        int
}

这段代码定义了一个名为DB的结构体,它包含以下字段:

  1. Config:指向 Config 结构体的指针,用于保存数据库连接的配置信息,例如地址、用户名、密码等。

  2. Error:最近一次执行数据库操作时发生的错误。

  3. RowsAffected:最近一次执行 insert、update 或 delete 操作时受影响的行数。

  4. Statement:指向 Statement 结构体的指针,用于保存当前正在执行的 SQL 语句相关的信息,例如预处理语句、参数等。

  5. clone:用于记录当前 DB 结构体的深度复制次数,主要用于某些特殊情况下的内部处理。

这个结构体似乎是 GORM 框架的核心结构体,用于管理数据库连接、执行 SQL 语句以及记录相关信息。

初始化 Gorm 库的 MySQL 数据库连接

func InitMySQL() {
	//自定义日志打印SQL语句
	newLogger := logger.New(
		log.New(os.Stdout, "\r\n", log.LstdFlags),
		logger.Config{
			SlowThreshold: time.Second, //慢SQL阈值
			LogLevel:      logger.Info, //级别
			Colorful:      true,        //彩色
		},
	)
	DB, _ = gorm.Open(mysql.Open(viper.GetString("mysql.dns")),
		&gorm.Config{Logger: newLogger})
}

这段代码定义了一个 InitMySQL 函数,其目的是初始化 Gorm 库的 MySQL 数据库连接。

函数中的参数 viper.GetString("mysql.dns") 返回了配置文件中 mysql.dns 键对应的字符串值,这个字符串表示 MySQL 数据库的连接地址、用户名和密码等信息。

接着,gorm.Open 函数通过给定的 MySQL 数据库连接信息创建一个 Gorm 的数据库连接实例,其中 mysql.Open 函数是 Gorm 提供的 MySQL 连接驱动程序,根据连接信息返回一个 *sql.DB 对象。

最后,&gorm.Config{Logger: newLogger} 通过 gorm.Config 中的 Logger 字段,将自定义的日志记录器与数据库连接绑定。该记录器可以在执行 SQL 语句时打印日志信息,如 SQL 语句、执行时间等。

数据库查询函数——utils.DB.Where()

gorm中Where源码

// Where add conditions
//
// See the [docs] for details on the various formats that where clauses can take. By default, where clauses chain with AND.
//
//	// Find the first user with name jinzhu
//	db.Where("name = ?", "jinzhu").First(&user)
//	// Find the first user with name jinzhu and age 20
//	db.Where(&User{Name: "jinzhu", Age: 20}).First(&user)
//	// Find the first user with name jinzhu and age not equal to 20
//	db.Where("name = ?", "jinzhu").Where("age <> ?", "20").First(&user)
//
// [docs]: https://gorm.io/docs/query.html#Conditions
func (db *DB) Where(query interface{}, args ...interface{}) (tx *DB) {
	tx = db.getInstance()
	if conds := tx.Statement.BuildCondition(query, args...); len(conds) > 0 {
		tx.Statement.AddClause(clause.Where{Exprs: conds})
	}
	return
}

这段代码是 GORM 框架中的方法,用于在 SQL 查询中添加 WHERE 子句的条件。
它接收一个 query 参数,可以是一个字符串或一个结构体指针,用于指定查询条件;
也可以在 query 参数中使用占位符(?)来传递参数,这样 GORM 会自动进行 SQL 注入防护。

例如,db.Where(“name = ?”, “jinzhu”) 表示添加一个查询条件,只查询 name 等于 “jinzhu” 的记录。
而 db.Where(&User{Name: “jinzhu”, Age: 20}) 表示使用结构体作为查询条件,只查询 name 等于 “jinzhu” 且 age 等于 20 的记录。
此外,你还可以链式使用 Where 方法添加多个条件,例如 db.Where(“name = ?”, “jinzhu”).Where(“age <> ?”, “20”)。

具体实现时,Where 方法首先调用 BuildCondition 方法构建查询条件,然后将其封装在一个 clause.Where 结构体中,最后调用 AddClause 方法将该结构体添加到当前 SQL 查询语句中。
最终返回一个新的 DB 对象,便于链式调用其他方法。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值