Go 数据库编程精粹:database/sql 实用技巧解析

Go 数据库编程精粹:database/sql 实用技巧解析

    • 简介
    • `database/sql` 库的基础知识
      • 核心概念
        • 连接池
        • 驱动
        • 事务
      • 环境配置
    • 建立数据库连接
      • 连接到数据库
      • 示例:连接 MySQL 数据库
      • 连接池管理
    • 执行查询和处理结果
      • 基本查询
        • 执行多行查询
        • 执行单行查询
      • 结果处理
        • 处理多行结果
        • 错误处理
      • 代码示例
    • 插入、更新和删除操作
      • 插入数据
      • 更新数据
      • 删除数据
      • 代码示例
    • 使用事务处理
      • 事务基础
      • 实践指南
      • 代码示例
    • 错误处理和优化
      • 错误处理
      • 性能优化
      • 代码示例
    • 高级主题
      • 预处理语句
      • 连接池管理
      • 高级查询技巧
    • 结语
      • 总结
      • 后续学习路径

在这里插入图片描述

简介

在现代软件开发中,数据库是不可或缺的组成部分。随着 Go 语言在云计算和网络服务开发领域的流行,了解其标准库中的 database/sql 包变得尤为重要。database/sql 是 Go 语言官方提供的数据库操作接口,它提供了一组丰富的功能,以支持开发者进行高效、可靠的数据库操作。

本文旨在为中高级开发者提供一个实战指南,深入探讨如何在 Go 语言中使用 database/sql 库。我们将不仅限于基础的数据库操作,还将涉及事务处理、错误管理、性能优化等高级主题。文章的重点在于提供实际可用的代码示例和最佳实践,以帮助读者在日常工作中快速应用。

值得注意的是,本文假设读者已具备基本的 Go 语言知识,以及一定的数据库操作经验。我们不会涉及 Go 语言的安装或其历史背景,而是直接聚焦于 database/sql 的使用。

通过本文,您将学会如何建立和维护数据库连接,执行各种数据库操作(如查询、插入、更新和删除),处理事务,以及进行错误处理和性能优化。我们还将探讨如何在 Go 中有效地管理数据库连接池,以及如何使用预处理语句提高应用程序的性能和安全性。

在文章的最后,我们将提供一些参考文献和进一步学习的资源,以帮助您在学习 database/sql 的旅程中更深入。

综上所述,本文是一份全面的指南,旨在帮助中高级 Go 开发者充分利用 database/sql 库,提高他们在数据库操作方面的技能和效率。无论您是正在开发大型云服务,还是处理复杂的数据集,本文都将为您提供宝贵的指导和支持。

database/sql 库的基础知识

database/sql 库是 Go 语言中处理数据库操作的核心库。它为不同类型的数据库提供了统一的接口,使得在 Go 应用程序中与数据库交互变得更为简洁和高效。本节将介绍一些基础概念和环境配置,为深入理解 database/sql 奠定基础。

核心概念

连接池

database/sql 库自动管理数据库连接池。这意味着它会维护一组已经打开的连接,并在需要时重用这些连接。这种机制提高了应用程序的性能,因为频繁地开启和关闭数据库连接是一项资源密集型操作。

驱动

虽然 database/sql 提供了统一的接口,但它本身并不包含任何数据库的实现。要与特定类型的数据库交互,需要使用相应的驱动。例如,要连接到 MySQL 数据库,您需要使用如 mysql 的驱动。

事务

database/sql 支持数据库事务,这是维护数据完整性和一致性的关键特性。事务确保了一系列操作要么全部执行,要么全部不执行,从而防止了部分更新导致的数据不一致问题。

环境配置

要在 Go 程序中使用 database/sql 库,首先需要配置好开发环境。这包括安装 Go 语言环境以及必要的数据库驱动。以下是一些基本步骤:

  1. 安装 Go 语言:确保您的系统中已安装了 Go 语言环境。可以在 Go 语言官网下载和安装。

  2. 安装数据库驱动:根据您将要连接的数据库类型,安装相应的驱动。例如,如果您打算使用 MySQL,可以通过运行 go get -u github.com/go-sql-driver/mysql 来安装 MySQL 驱动。

  3. 设置环境变量:根据需要设置相关的环境变量,如数据库连接字符串等。

完成这些配置后,您就可以开始在 Go 程序中使用 database/sql 库来进行数据库操作了。

建立数据库连接

在 Go 语言的 database/sql 库中,建立与数据库的连接是任何数据库操作的起点。这一节将指导您如何在 Go 程序中创建和配置数据库连接。

连接到数据库

要连接到数据库,首先需要构建一个数据库连接字符串,然后使用 sql.Open 函数建立连接。以下是连接不同类型数据库的通用步骤:

  1. 构建连接字符串:这是一个包含数据库类型、访问凭据、服务器地址、端口号和数据库名等信息的字符串。每种数据库的格式略有不同。

  2. 使用 sql.Open 连接:调用 sql.Open(driverName, dataSourceName) 函数来建立连接。driverName 是数据库驱动的名称,dataSourceName 是连接字符串。

示例:连接 MySQL 数据库

假设您需要连接到一个 MySQL 数据库。首先,确保已经安装了 MySQL 驱动(如前文所述)。然后,使用以下步骤建立连接:

import ("database/sql"_ "github.com/go-sql-driver/mysql"
)func main() {// 构建连接字符串// 格式通常为:username:password@protocol(address)/dbname?param=valuedataSourceName := "user:password@tcp(localhost:3306)/dbname"// 建立连接db, err := sql.Open("mysql", dataSourceName)if err != nil {log.Fatal(err)}defer db.Close()// ... 后续数据库操作
}

在这个示例中,首先导入了 database/sql 库和 MySQL 驱动。然后,构建了一个连接字符串,并使用 sql.Open 建立连接。注意,即使连接可能未立即建立,sql.Open 也不会返回错误。要验证连接是否成功,可以尝试使用 db.Ping()

连接池管理

database/sql 库管理着一个内部连接池。这意味着,当您使用 sql.Open 时,并不会立即创建一个新的数据库连接,而是可能从池中获取一个现有的连接。连接池的这种行为减少了创建和销毁连接的开销,提高了应用程序的性能。

通过适当的设置,您可以控制连接池的行为,例如设置最大打开连接数、最大空闲连接数等。例如:

db.SetMaxOpenConns(25)
db.SetMaxIdleConns(5)
db.SetConnMaxLifetime(time.Minute * 5)

这些设置有助于优化应用程序与数据库的交互,确保资源得到有效利用。

执行查询和处理结果

在 Go 的 database/sql 库中,执行查询并处理返回的结果是数据库交互的核心。本节将介绍如何执行 SQL 查询,并如何处理查询返回的数据。

基本查询

执行 SQL 查询的基本步骤是使用 db.Query()db.QueryRow() 函数。db.Query() 用于执行返回多行结果的查询,而 db.QueryRow() 用于执行仅返回单行结果的查询。

执行多行查询

当查询可能返回多行数据时,可以使用 db.Query()。例如,查询数据库中的所有记录:

rows, err := db.Query("SELECT id, name FROM users")
if err != nil {log.Fatal(err)
}
defer rows.Close()for rows.Next() {var id intvar name stringif err := rows.Scan(&id, &name); err != nil {log.Fatal(err)}fmt.Printf("%d: %s\n", id, name)
}if err := rows.Err(); err != nil {log.Fatal(err)
}

这个例子中,rows.Next() 遍历查询结果中的每一行,而 rows.Scan() 则将行中的列映射到相应的变量中。

执行单行查询

对于只期望返回单行结果的查询,使用 db.QueryRow() 更为合适。它会返回一个 *sql.Row 对象,表示单个行记录。

var name string
err := db.QueryRow("SELECT name FROM users WHERE id = ?", 1).Scan(&name)
if err != nil {if err == sql.ErrNoRows {fmt.Println("No rows were returned!")} else {log.Fatal(err)}
}
fmt.Println(name)

在这个例子中,如果查询没有返回行,则 Scan 会返回 sql.ErrNoRows 错误。

结果处理

处理多行结果

当处理 db.Query() 返回的多行结果时,重要的是要关闭 rows 对象,以释放占用的资源。这通常是通过 defer rows.Close() 实现的。

错误处理

在迭代结果集时,需要注意对错误进行适当的处理。rows.Next() 在遍历结束或出现错误时返回 false。在循环外部,使用 rows.Err() 检查循环过程中是否发生了任何错误。

代码示例

以下是一个更复杂的查询示例,展示了如何在 Go 中使用 database/sql 执行查询并处理结果:

type User struct {ID   intName string
}var users []Userrows, err := db.Query("SELECT id, name FROM users WHERE age > ?", 18)
if err != nil {log.Fatal(err)
}
defer rows.Close()for rows.Next() {var u Userif err := rows.Scan(&u.ID, &u.Name); err != nil {log.Fatal(err)}users = append(users, u)
}if err := rows.Err(); err != nil {log.Fatal(err)
}for _, user := range users {fmt.Printf("%d: %s\n", user.ID, user.Name)
}

在这个例子中,我们查询了所有年龄超过 18 岁的用户,并将结果存储在一个 User 类型的切片中。

插入、更新和删除操作

在数据库的日常操作中,除了查询数据外,插入、更新和删除数据同样重要。database/sql 库为这些操作提供了清晰、简洁的方法。

插入数据

要在数据库中插入新记录,可以使用 db.Exec() 方法。这个方法对于不需要返回结果的 SQL 命令(如 INSERT、UPDATE、DELETE)非常有用。

stmt, err := db.Prepare("INSERT INTO users(name, age) VALUES(?, ?)")
if err != nil {log.Fatal(err)
}
defer stmt.Close()res, err := stmt.Exec("John Doe", 28)
if err != nil {log.Fatal(err)
}lastId, err := res.LastInsertId()
if err != nil {log.Fatal(err)
}
fmt.Printf("插入记录的 ID: %d\n", lastId)

在这个例子中,首先准备了一个 SQL 语句,然后执行它并插入新数据。Exec 方法返回一个 sql.Result 对象,可以用来获取关于操作的一些信息,比如最后插入行的 ID。

更新数据

更新操作与插入操作类似,也是使用 db.Exec() 方法。以下示例展示了如何更新表中的记录:

res, err := db.Exec("UPDATE users SET age = ? WHERE name = ?", 30, "John Doe")
if err != nil {log.Fatal(err)
}affected, err := res.RowsAffected()
if err != nil {log.Fatal(err)
}
fmt.Printf("影响的行数: %d\n", affected)

这个例子更新了名为 “John Doe” 的用户的年龄,并返回了受影响的行数。

删除数据

删除数据也是使用 db.Exec() 方法。以下是一个删除记录的例子:

res, err := db.Exec("DELETE FROM users WHERE age < ?", 20)
if err != nil {log.Fatal(err)
}affected, err := res.RowsAffected()
if err != nil {log.Fatal(err)
}
fmt.Printf("删除的行数: %d\n", affected)

在这个例子中,删除了所有年龄小于 20 岁的用户,并返回了删除的行数。

代码示例

以上三个操作示例展示了如何在 Go 使用 database/sql 库进行基本的数据库写操作。通过这些示例,可以看出 database/sql 提供了一种既简洁又强大的方式来执行数据库的插入、更新和删除操作。

使用事务处理

在数据库操作中,事务是确保数据完整性和一致性的关键机制。database/sql 库支持事务操作,允许您在发生错误时回滚更改,以保持数据状态的一致性。

事务基础

事务是一系列操作,它们作为一个整体被执行。要么所有操作都成功执行,要么在出现错误时全部撤销。这被称为原子性。在 Go 的 database/sql 应用中,事务的使用遵循以下基本步骤:

  1. 开始事务:使用 db.Begin() 开始一个新的事务。
  2. 执行操作:在事务中执行一系列数据库操作。
  3. 提交或回滚:如果所有操作成功,使用 tx.Commit() 提交事务。如果出现错误,使用 tx.Rollback() 回滚事务。

实践指南

以下是使用事务的一个简单示例:

tx, err := db.Begin()
if err != nil {log.Fatal(err)
}_, err = tx.Exec("INSERT INTO users(name, age) VALUES(?, ?)", "Jane Doe", 28)
if err != nil {tx.Rollback()log.Fatal(err)
}_, err = tx.Exec("UPDATE users SET age = ? WHERE name = ?", 29, "Jane Doe")
if err != nil {tx.Rollback()log.Fatal(err)
}err = tx.Commit()
if err != nil {log.Fatal(err)
}

在这个例子中,我们首先开始一个新的事务。然后执行两个数据库操作:插入一个新用户和更新这个用户的年龄。如果其中任何一个操作失败,事务将回滚,撤销之前的操作。如果所有操作都成功,事务将被提交。

代码示例

事务处理对于保持数据库的完整性至关重要,尤其是在处理复杂的数据更新时。database/sql 库提供了一套直观的 API 来处理事务,使得在 Go 程序中管理事务变得简单而高效。

错误处理和优化

有效的错误处理和性能优化是提高数据库应用程序稳定性和效率的关键。database/sql 库提供了工具和策略来帮助开发者在这两个方面取得进展。

错误处理

在使用 database/sql 时,正确的错误处理不仅可以帮助您识别问题,还可以防止应用程序在遇到数据库问题时崩溃。以下是一些常见的错误处理策略:

  1. 检查错误返回:几乎所有 database/sql 的操作都会返回错误。始终检查并适当处理这些错误是很重要的。

  2. 区分错误类型:了解并区分不同类型的错误(如 sql.ErrNoRows)可以帮助您更精确地处理特定情况。

  3. 使用事务处理错误:在事务中,如果任何步骤失败,应该回滚整个事务,以保持数据的一致性。

性能优化

对数据库操作进行性能优化可以显著提高应用程序的响应速度和效率。以下是一些优化 database/sql 使用的技巧:

  1. 使用连接池database/sql 默认使用连接池。正确配置连接池(如设置最大打开连接数和最大空闲连接数)可以帮助减少开启和关闭连接的频繁性,从而提高性能。

  2. 预处理语句:预处理语句可以提高数据库操作的效率,并提供一定程度的安全性。使用 db.Prepare() 可以创建一个预处理语句,然后多次执行。

  3. 批量操作:对于插入和更新等操作,批量处理可以减少数据库交互的次数,从而提高效率。

代码示例

以下是一个展示如何在 Go 中使用 database/sql 进行错误处理和性能优化的示例:

// 预处理语句示例
stmt, err := db.Prepare("INSERT INTO users(name, age) VALUES(?, ?)")
if err != nil {log.Fatal(err)
}
defer stmt.Close()for _, user := range users {_, err := stmt.Exec(user.Name, user.Age)if err != nil {log.Fatal(err)}
}// 批量更新示例
tx, err := db.Begin()
if err != nil {log.Fatal(err)
}for _, user := range users {_, err := tx.Exec("UPDATE users SET age = ? WHERE name = ?", user.Age, user.Name)if err != nil {tx.Rollback()log.Fatal(err)}
}err = tx.Commit()
if err != nil {log.Fatal(err)
}

在这个例子中,使用了预处理语句来插入多个用户,同时使用事务来执行批量更新操作。

高级主题

在掌握了 database/sql 的基础操作后,探索一些高级主题可以帮助您更全面地利用这个库的强大功能。本节将介绍预处理语句的使用、连接池管理以及一些高级查询技巧。

预处理语句

预处理语句是提高数据库操作性能和安全性的有效工具。通过预编译 SQL 语句,可以减少 SQL 注入的风险,并提高查询的效率。

database/sql 中,可以使用 db.Prepare() 创建预处理语句:

stmt, err := db.Prepare("SELECT name FROM users WHERE age > ?")
if err != nil {log.Fatal(err)
}
defer stmt.Close()rows, err := stmt.Query(18)
if err != nil {log.Fatal(err)
}
defer rows.Close()for rows.Next() {var name stringif err := rows.Scan(&name); err != nil {log.Fatal(err)}fmt.Println(name)
}

在这个示例中,创建了一个预处理查询语句,然后执行了该语句并处理了结果。

连接池管理

合理管理数据库连接池对于确保应用程序性能和稳定性至关重要。database/sql 自动管理连接池,但您可以通过一些设置来优化其行为:

  • SetMaxOpenConns 设置连接池中的最大打开连接数。
  • SetMaxIdleConns 设置连接池中的最大空闲连接数。
  • SetConnMaxLifetime 设置连接的最大存活时间。

这些设置可以帮助您平衡性能和资源利用,避免过多的数据库连接导致资源浪费。

高级查询技巧

除了基本的 CRUD 操作外,database/sql 还支持更复杂的查询和数据库操作。例如,您可以执行带有子查询、连接和复杂条件的 SQL 语句。这些高级特性可以帮助您处理更复杂的数据检索和分析任务。

query := `
SELECT u.name, u.age, COUNT(o.id) as order_count
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
WHERE u.age > ?
GROUP BY u.id`rows, err := db.Query(query, 18)
if err != nil {log.Fatal(err)
}for rows.Next() {var name stringvar age intvar orderCount intif err := rows.Scan(&name, &age, &orderCount); err != nil {log.Fatal(err)}fmt.Printf("%s (%d years): %d orders\n", name, age, orderCount)
}

在这个示例中,我们执行了一个更复杂的查询,它涉及到连接和聚合操作。

结语

通过本文,我们深入探讨了 Go 语言中 database/sql 库的使用,从基本的数据库连接和查询操作,到高级的事务处理、错误管理和性能优化。这些知识点不仅是构建高效、可靠的 Go 数据库应用程序的基石,也为处理更复杂的数据管理任务提供了坚实的基础。

总结

我们开始于 database/sql 的基础概念,理解了如何建立数据库连接,并学习了执行基本的 CRUD 操作。接着,我们探索了事务处理的要点,了解了如何使用事务来确保数据操作的一致性和完整性。在错误处理和优化部分,我们学习了如何有效地处理可能出现的错误,并采取措施提高应用程序的性能。最后,我们探讨了一些高级主题,如预处理语句和复杂查询技巧,以进一步提升我们的技能。

后续学习路径

虽然本文涵盖了 database/sql 的许多重要方面,但学习之旅不应止步于此。为了更全面地掌握 Go 语言和数据库交互,建议继续深入学习以下几个方面:

  • 探索不同的数据库驱动:了解如何使用 Go 与不同类型的数据库(如 PostgreSQL、SQLite 等)交互。
  • 深入理解 Go 的并发模型:了解如何在并发环境中安全有效地使用 database/sql
  • 实践复杂的数据库应用场景:比如数据分析、大数据处理等。

最后,希望这篇文章能够成为您在 Go 数据库编程旅程中的宝贵资源。持续实践并探索新知识,您将能够构建更加强大和高效的数据库应用程序。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于Java SSM框架实现问卷调查系统项目【项目源码】

基于java的SSM框架实现问卷调查系统演示 B/S结构 BROWSER/SERVER程序架构方式是使用电脑中安装的各种浏览器来进行访问和使用的&#xff0c;相比C/S的程序结构不需要进行程序的安装就可以直接使用。BROWSER/SERVER架构的运行方式是在远程的服务器上进行安装一个&#xff0c;然…

普中51单片机学习(DS1302)

DS1302时钟 DS1302实时时钟具有能计算2100年之前的秒、分、时、日、日期、星期、月、年的能力&#xff0c;还有闰年调整的能力。内部含有31个字节静态RAM&#xff0c;可提供用户访问。采用串行数据传送方式&#xff0c;使得管脚数量最少&#xff0c;简单SPI 3线接口。工作电压…

4.8 Verilog过程连续赋值

关键词&#xff1a;解除分配&#xff0c;强制&#xff0c;释放 过程连续赋值是过程赋值的一种。赋值语句能够替换其他所有wire 或 reg 的赋值&#xff0c;改写wire 或 reg 类型变量的当前值。 与过程赋值不同的是&#xff0c;过程连续赋值表达式能被连续的驱动到wire 或 reg …

C++——基础语法(2):函数重载

4. 函数重载 函数重载就是同一个函数名可以重复被定义&#xff0c;即允许定义相同函数名的函数。但是相同名字的函数怎么在使用的时候进行区分呢&#xff1f;所以同一个函数名的函数之间肯定是要存在不同点的&#xff0c;除了函数名外&#xff0c;还有返回类型和参数两部分可以…

本地配置多个git账户及ll设置

本地配置多个git账户 清除全局配置将命令行&#xff0c;切换到ssh目录生成GitLab和Gitee的公钥、私钥去对应的代码仓库添加 SSH Keys添加私钥ll设置 管理密钥验证仓库配置关于gitgitee.com: Permission denied (publickey) 清除全局配置 此步骤可以不做&#xff0c;经测试不影…

总结一下最近几个主界面

目前展示了用Avalonia做几个主要流行的主界面&#xff0c;演示了一下组件的使用。用不同的实现方式实现一些方法。 1、独立大屏展示&#xff0c;类似一个实时监控&#xff0c;这是一种目前很方便的大屏效果。 主要涉及的内内容&#xff1a; &#xff08;1&#xff09;窗标题实…

【视频编码\VVC】环路滤波基础知识

本文为新一代通用视频编码H.266\VVC原理、标准与实现的简化笔记。 定义&#xff1a;在视频编码过程中进行滤波&#xff0c;滤波后的图像用于后续编码。 目的&#xff1a;1、提升编码图像的质量。2、为后续编码图像提供高质量参考&#xff0c;获得更好的预测效果。 VVC中主要…

使用LinkedList实现堆栈及Set集合特点、遍历方式、常见实现类

目录 一、使用LinkedList实现堆栈 堆栈 LinkedList实现堆栈 二、集合框架 三、Set集合 1.特点 2.遍历方式 3.常见实现类 HashSet LinkedHashSet TreeSet 一、使用LinkedList实现堆栈 堆栈 堆栈&#xff08;stack&#xff09;是一种常见的数据结构&#xff0c;一端…

后端程序员入门react笔记(五)ajax请求

常见的ajax Ajax 最原始的方式&#xff0c;基于原生的jsXmlHttpRequest 多个请求之间如果有先后关系&#xff0c;会存在很多层回调的问题&#xff0c;也是基于原生jsJquery Ajax 基于原生XHR封装&#xff0c;依赖Jquery框架&#xff0c;由jquery 框架去封装原生的XML(Xml)封装…

【高德地图】Android高德地图控件交互详细介绍

&#x1f4d6;第5章 与地图控件交互 ✅控件交互&#x1f9ca;缩放按钮&#x1f9ca;指南针&#x1f9ca;定位按钮&#x1f9ca;地图Logo ✅手势交互&#x1f9ca;缩放手势&#x1f9ca;滑动手势&#x1f9ca;旋转手势&#x1f9ca;倾斜手势&#x1f9ca;指定屏幕中心点的手势操…

CSP-J 2023 T1 小苹果

文章目录 题目题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 提示 题目传送门题解思路总代码 提交结果尾声 题目 题目描述 小 Y 的桌子上放着 n n n 个苹果从左到右排成一列&#xff0c;编号为从 1 1 1 到 n n n。 小苞是小 Y 的好朋友&#xff0c;每天她都会从…

EXCEL 在列不同单元格之间插入N个空行

1、第一步数据&#xff0c;要求在每个数字之间之间插入3个空格 2、拿数据个数*&#xff08;要插入空格数1&#xff09; 19*4 3、填充 4、复制数据到D列 5、下拉数据&#xff0c;选择复制填充这样1-19就会重复4次 6、全选数据D列排序&#xff0c;这样即完成了插入空格 以…

密评技术要求实施详解:每一步都关键

密评简介 密评定义&#xff1a;全称商用密码应用安全性评估, 是对采用商用密码技术、产品和服务集成建设的网络和信息系统密码应用的合规性、正确性、有效性进行评估的活动。 评测依据&#xff1a;GB/T 39786-2021《信息安全技术 信息系统密码应用基本要求》。 密评对象&…

新能源汽车PACK电池包的气密性测试需要用到哪些快速密封连接器

PACK电池包是新能源汽车的重要部件之一&#xff0c;在全部组装完成后需要对其壳体进行气密性测试&#xff0c;以确保壳体的密封性能&#xff0c;避免有雨水、灰尘等外界侵扰拒之门外&#xff0c;从而保证电池的使用寿命不受损害。 新能源汽车PACK电池包 在做气密性测试时需要用…

Jmeter基础(3) 发起一次请求

目录 Jmeter 一次请求添加线程组添加HTTP请求添加监听器 Jmeter 一次请求 用Jmeter进行一次请求的过程&#xff0c;需要几个步骤呢&#xff1f; 1、添加线程组2、添加HTTP请求3、添加监听器&#xff0c;查看结果树 现在就打开jmeter看下如何创建一个请求吧 添加线程组 用来…

CUDA自学笔记001 CUDA编程模型、CUDA线程模型及其管理、CUDA内存模型及其管理

CUDA编程模型 我们使用CUDA_C语言进行CUDA编程&#xff0c; 1&#xff0c;CUDA编程模型提供了线程抽象接口用于控制GPU中的线程 2&#xff0c;CUDA编程模型提供了内存访问控制&#xff0c;我们可以实现主机和GPU设备内存的控制&#xff0c;我们可以实现CPU和GPU之间内存的数据传…

yolov5-tracking-xxxsort yolov5融合六种跟踪算法(三)--目标跟踪

本次开源计划主要针对大学生无人机相关竞赛的视觉算法开发。 开源代码仓库链接&#xff1a;https://github.com/zzhmx/yolov5-tracking-xxxsort.git 先按照之前的博客配置好环境&#xff1a; yolov5-tracking-xxxsort yolov5融合六种跟踪算法&#xff08;一&#xff09;–环境配…

【论文阅读笔记】Revisiting RCAN: Improved Training for Image Super-Resolution

论文地址&#xff1a;https://arxiv.org/abs/2201.11279 代码地址&#xff1a;https://github.com/zudi-lin/rcan-it 论文小结 本文的工作&#xff0c;就是重新审视之前的RCAN&#xff0c;然后做实验来规范化SR任务的训练流程。 此外&#xff0c;作者得出一个结论&#xff1a;…

单片机51 输入和输出

一、IO口基本概念介绍 单片机的IO口&#xff08;Input/Output口&#xff09;是连接单片机与外部电路或设备的接口。单片机的IO口可以分为输入口和输出口两种&#xff0c;用于控制和监测外部设备的状态。 1. 输入口&#xff1a;单片机的输入口用于接收外部电路或设备的信号。输…

❤ hexo主题+Gitee搭建个人博客

Hexo的基本使用 ​官网 官网地址&#xff1a;https://hexo.io/zh-cn/ Hexo是一个快速、简洁且高效的博客框架。Hexo 使用 Markdown&#xff08;或其他渲染引擎&#xff09;解析文章&#xff0c;在几秒内&#xff0c;即可利用靓丽的主题生成静态网页。即把用户的markdown文件…