前言
- 最近搓了学生管理系统和留言板系统,不过对里面的函数摸棱两可,不太熟悉,于是便有了此次汇总,巩固复习一下。
- 这里涵盖的主要是这两个系统所涉及的函数,可能不太全面。
一、与Gin框架相关
1.gin.Context:
gin.Context虽然只是一个类型,但是它遍布大多数Gin框架函数中,所以我们优先来讲讲它。- 它用于在
gin的中间件和处理函数中传递请求相关的上下文信息,包括请求数据、响应数据以及控制请求流程的方法等。可以把它看作是一个包含了一次 HTTP 请求和响应的所有信息的容器。 - 其包含众多方法,后面我们只讲它的主要方法。
Param:
-
功能:用于获取路由中的路径参数。当定义带有参数的路由,如
/user/:id,Param方法可以获取:id对应的实际值。 -
示例:
router.GET("/user/:id", func(c *gin.Context) {
userID := c.Param("id")
// 可以根据userID进行数据库查询等操作
})
Query 和 GetQuery:
- 功能:
Query用于获取 URL 中的查询参数。例如,对于/search?q=golang,可以用c.Query("q")获取q的值。如果查询参数不存在,Query空字符串。GetQuery与Query类似,但当查询参数不存在时,GetQuery返回nil,而不是空字符串。
- 示例:
router.GET("/search", func(c *gin.Context) {
query := c.Query("q")
// 根据query进行搜索逻辑等操作
})
BindJSON 和 ShouldBindJSON:
- 功能:
BindJSON用于将请求体中的 JSON 数据解析到指定的结构体中。它会根据 JSON 数据的格式和结构体的定义进行解析。如果解析成功,会将数据填充到结构体中;如果解析失败,会返回错误。ShouldBindJSON的功能与BindJSON类似,但它不会在解析失败时返回错误,而是直接返回解析后的数据(可能部分填充或者为空)。
- 示例:
type User struct {
Name string `json:"name"`
Age int `json:"age"`
Email string `json:"email"`
}
router.POST("/user", func(c *gin.Context) {
var user User
if err := c.BindJSON(&user); err == nil {
// 成功解析JSON数据,可以进行用户创建等操作
} else {
// 处理解析错误
}
})
- 注意事项:
- 结构体中的字段标签(如
json:"name")需要与 JSON 数据中的键名相对应,否则可能导致解析错误。 - 被解析的结构体需要是可寻址的(使用
&符号),这样才能将数据填充进去。
- 结构体中的字段标签(如
JSON:
- 功能:用于返回 JSON 格式的响应。它会将传入的数据结构(如
map、struct等)转换为 JSON 格式,并设置Content - Type为application/json,然后将数据发送给客户端。 - 示例:
router.GET("/data", func(c *gin.Context) {
data := map[string]interface{}{
"message": "This is a JSON response",
"status": true,
}
c.JSON(http.StatusOK, data)
})
- 注意事项:
- 要注意传入
JSON方法的数据结构是否符合要求,例如不能包含不可导出的字段(以小写字母开头的字段),否则这些字段将不会被转换为 JSON。 - 如果在返回 JSON 数据的过程中出现错误,可能是由于各种原因导致的,需要进行适当的错误处理。
- 要注意传入
Abort:
- 功能:
Abort用于立即终止当前请求的处理流程。当Abort被调用后,gin将不会执行当前请求处理函数中Abort调用之后的代码,也不会执行后续的中间件(那些还没有被执行的)。 - 示例:
func AuthMiddleware(c *gin.Context) {
token := c.Request.Header.Get("Authorization")
if!isValidToken(token) {
c.JSON(http.StatusUnauthorized, gin.H{"message": "Unauthorized"})
c.Abort()
}
// 如果令牌有效,继续执行后续中间件或请求处理函数
}
Next:
- 功能:在中间件中起到关键作用,用于控制中间件的执行顺序。当在中间件中调用
c.Next()时,会暂停当前中间件的执行,转而去执行下一个中间件或者请求处理函数。在所有后续的中间件和请求处理函数执行完毕后,会回到当前中间件继续执行剩余的代码。 - 示例:
func AuthMiddleware(c *gin.Context) {
token := c.Request.Header.Get("Authorization")
if!isValidToken(token) {
c.JSON(http.StatusUnauthorized, gin.H{"message": "Unauthorized"})
c.Abort()
}
c.Next()
}
- 注意事项:
- 正确理解
Next的执行流程对于编写复杂的中间件逻辑非常重要。如果在中间件中没有调用Next,那么后续的中间件和请求处理函数将不会被执行。 - 可以在
Next之后编写一些在请求处理完成后需要执行的代码,比如记录响应信息、关闭数据库连接等。
- 正确理解
SetCookie:
- 功能:用于在 HTTP 响应中设置一个 Cookie。
- 参数解释:
name参数:这是 Cookie 的名称。value参数:Cookie 的值,它可以是任何字符串类型的数据。maxAge参数:用于设置 Cookie 的生存时间,path参数:指定 Cookie 有效的路径。domain参数:指定 Cookie 有效的域名。secure参数:这是一个布尔值。如果设置为true,则表示只有在通过HTTPS协议访问时才会发送这个 Cookie,这有助于提高安全性。
httpOnly参数:也是一个布尔值。如果设置为true,则表示这个 Cookie 不能通过 JavaScript 访问,只能在 HTTP(或 HTTPS)请求中发送,这可以防止跨站脚本攻击(XSS)获取 Cookie 信息。
- 示例:
func main() {
router := gin.Default()
router.GET("/set - cookie", func(c *gin.Context) {
c.SetCookie("username", "John Doe", 3600, "/", "localhost", false, true)
c.JSON(http.StatusOK, gin.H{"message": "Cookie has been set"})
})
router.Run(":8080")
}
- 注意事项:
cookie可能导致安全问题,这里不多赘述。
2.Router(路由器):
Router不是函数也不是类型,是路由器的英文。- 在函数中,我们常用
r来代表路由器。此部分我们讲讲跟路由器相关的函数。
Default:
- 功能:
Default是gin框架中用于创建一个默认的gin.Engine实例的函数。这个默认的引擎包含了Logger和Recovery两个中间件。Logger中间件用于记录请求的日志信息,包括请求方法、请求路径、响应状态码和处理时间等。Recovery中间件用于捕获panic,防止服务器因为意外的panic而崩溃。 - 示例:
func main() {
router := gin.Default()
// 在这里定义路由
router.Run(":8080")
}
- 注意事项:如果不需要这两个默认中间件,可以使用
gin.New()来创建一个没有任何中间件的gin.Engine实例,然后再根据需要添加中间件。
GET、POST、PUT、DELETE等 HTTP 方法相关函数:
- 功能:这些函数用于在
gin引擎上定义不同 HTTP 方法的路由。例如,GET用于定义处理GET请求的路由,POST用于定义处理POST请求的路由等。它们的第一个参数是路由路径,第二个参数是一个gin.HandlerFunc类型的函数,这个函数用于处理对应的请求。 - 示例(此处只举
GET的例子):- 这个例子定义了一个处理GET请求的路由,当用户访问/hello路径时,会返回Hello, World!字符串。
router.GET("/hello", func(c *gin.Context) {
c.String(http.StatusOK, "Hello, World!")
})
- 注意事项:
- 路由路径可以包含参数,例如
/user/:id,其中id是参数。在处理函数中可以通过c.Param("id")来获取参数的值。 - 对于
POST、PUT等可能带有请求体的请求方法,需要注意正确处理请求体内容,如使用BindJSON等方法来解析请求体。
- 路由路径可以包含参数,例如
Group:
- 功能:
Group函数用于创建路由组。路由组可以让你将相关的路由进行分组管理,并且可以为路由组统一添加中间件。 - 示例:
userGroup := router.Group("/user")
{
userGroup.GET("/:id", func(c *gin.Context) {
// 获取用户信息
})
userGroup.POST("/", func(c *gin.Context) {
// 创建用户
})
}
- 注意事项:
- 路由组中的路径是相对于组路径的。在上面的例子中,
GET请求的实际路径是/user/:id,POST请求的实际路径是/user/。
- 路由组中的路径是相对于组路径的。在上面的例子中,
Use:
- 功能:
Use函数用于将中间件添加到gin引擎或者路由组中。中间件是一种在请求处理过程中可以执行额外逻辑的组件,例如日志记录、权限验证、性能监控等。通过Use函数,可以确保这些中间件在处理对应的请求时按照添加的顺序被执行。 - 示例(路由组中间件):
func AuthMiddleware(c *gin.Context) {
token := c.Request.Header.Get("Authorization")
if!isValidToken(token) {
c.JSON(http.StatusUnauthorized, gin.H{"message": "Unauthorized"})
c.Abort()
} else {
c.Next()
}
}
userGroup := router.Group("/user")
userGroup.Use(AuthMiddleware)
{
userGroup.GET("/:id", func(c *gin.Context) {
// 获取用户信息,只有通过权限验证才能执行到这里
})
userGroup.POST("/", func(c *gin.Context) {
// 创建用户,同样只有通过权限验证才能执行到这里
})
}
// 后续定义路由
Run:
- 功能:
Run函数用于启动gin服务器,使它开始监听指定的端口并处理请求。它会将gin引擎绑定到一个网络地址(通常是一个 IP 地址和端口号),然后等待客户端的 HTTP 请求并进行处理。 - 示例:这个例子中,
gin服务器会监听本地的8080端口。当有客户端发送 HTTP 请求到http://localhost:8080或者对应的 IP 地址和端口组合时,服务器会根据定义的路由和中间件来处理这些请求。
router := gin.Default()
// 定义路由
router.Run(":8080")
二、与MySql相关
数据库操作相关的函数:
sql.Open:
- 功能:
sql.Open函数用于初始化一个数据库连接。对于 MySQL 数据库,它接收两个参数,第一个参数是驱动名称(固定为"mysql"),第二个参数是数据库连接字符串。连接字符串包含了数据库的位置、用户名、密码以及数据库名称等信息,格式一般为user:password@tcp(host:port)/database。 - 示例:
func main() {
// 打开数据库连接
db, err := sql.Open("mysql", "user:password@tcp(127.0.0.1:3306)/mydb")
if err!= nil {
// 处理错误,可能是驱动未正确安装或者连接字符串有误
panic(err)
}
// 在这里可以使用db对象进行数据库操作
}
- 注意事项:
sql.Open函数只是初始化了一个数据库连接对象,并没有真正建立连接。真正的连接是在第一次执行数据库操作(如Query、Exec等)时建立的。- 导入 MySQL 驱动
_ "github.com/go - sql - driver/mysql"这一行是必要的,虽然前面有个_,表示只导入包进行初始化而不使用包中的变量等,但它会注册 MySQL 驱动,使得sql.Open中的"mysql"驱动名称能够正确对应。
db.Query和db.QueryRow:
- 功能:
db.Query:用于执行一个查询语句(如SELECT语句),它返回一个*sql.Rows对象,这个对象包含了查询结果的所有行。可以通过遍历sql.Rows来获取每一行的数据。db.QueryRow:用于执行一个只期望返回一行结果的查询语句。它返回一个*sql.Row对象,通过Scan方法可以将查询结果扫描到对应的变量中。
- 示例:
db.Query示例(代码1)和db.QueryRow示例(代码2):
// 假设db是已经打开的数据库连接对象
rows, err := db.Query("SELECT id, name, age FROM users")
if err!= nil {
// 处理查询错误
panic(err)
}
defer rows.Close()
for rows.Next() {
var id int
var name string
var age int
err = rows.Scan(&id, &name, &age)
if err!= nil {
// 处理扫描错误
panic(err)
}
// 处理每一行数据,例如打印
println(id, name, age)
}
var name string
var age int
err = db.QueryRow("SELECT name, age FROM users WHERE id =?", 1).Scan(&name, &age)
if err!= nil {
// 处理错误,可能是没有找到对应的行或者其他查询错误
panic(err)
}
// 处理获取到的一行数据,例如打印
println(name, age)
db.Exec:
- 功能:
db.Exec用于执行非查询语句,如INSERT、UPDATE、DELETE等语句。它返回一个sql.Result对象,这个对象包含了受影响的行数等信息。 - 示例:
cmd := "INSERT INTO users(nickname,username,password) VALUES (?,?,?);"
result, err := db.Exec(cmd, user.Nickname, user.Username, user.Password)
if err != nil {
client.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
结语
- 以上函数是我在搓学管和留言板时用到的函数,gin框架封装了很多很好的函数我并没有用上。这里只占很小一部分。
- 这篇文章相当一部分内容引用了ai的回答。
- 这篇文章主要是留下为我日后复习做准备。写了两个小时终于写完了,希望这篇文章能够帮到你。
2540

被折叠的 条评论
为什么被折叠?



