当前位置: 首页 > news >正文

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 数据库编程旅程中的宝贵资源。持续实践并探索新知识,您将能够构建更加强大和高效的数据库应用程序。

相关文章:

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

Go 数据库编程精粹&#xff1a;database/sql 实用技巧解析 简介database/sql 库的基础知识核心概念连接池驱动事务 环境配置 建立数据库连接连接到数据库示例&#xff1a;连接 MySQL 数据库连接池管理 执行查询和处理结果基本查询执行多行查询执行单行查询 结果处理处理多行结果…...

AI-Gateway:一款整合了OpenAI、Anthropic、LLama2等大语言模型的统一API接口

关于AI-Gateway AI-Gateway是一款针对大语言模型的统一API接口&#xff0c;该接口可以用在应用程序和托管的大语言模型&#xff08;LLM&#xff09;之间&#xff0c;该工具可以允许我们通过一个统一的API接口将API请求转发给OpenAI、Anthropic、Mistral、LLama2、Anyscale、Go…...

Android 广播的基本概念

一.广播简介 Broadcast是安卓四大组件之一。安卓为了方便进行系统级别的消息通知&#xff0c;引入了一套广播消息机制。打个比方&#xff0c;记得原来在上课的时候&#xff0c;每个班级的教室里都会装有一个喇叭&#xff0c;这些喇叭都是接入到学校的广播室的&#xff0c;一旦…...

【Docker实操】部署php项目

概述 最终达成的容器部署结构和原理如下图&#xff1a; 一、获取nginx、php官方镜像 docker pull nginx //拉取nginx官方镜像 docker pull php:7.4-fpm //拉取php官方镜像需要获取其他可用的php版本&#xff0c;可以上【docker hub】搜索【php】&#xff0c;所有的【xxx-fp…...

多线程-初阶

1. 认识线程&#xff08; Thread &#xff09; 1.1 概念 1) 线程是什么 一个线程就是一个 " 执行流 ". 每个线程之间都可以按照顺讯执行自己的代码 . 多个线程之间 " 同时 " 执行 着多份代码 . 还是回到我们之前的银行的例子中。之前我们主要描…...

Object和Function是函数,函数都有一个prototype属性

Object 和 Function 都是 JavaScript 自带的函数对象 在 JavaScript 中&#xff0c;万物皆对象&#xff0c;你要一个吗&#xff1f;new Object() 啊&#xff01; 当然&#xff0c;就好比同样为人&#xff0c;也区分普通人和天才。 对象也是有分类的&#xff0c;分为 普通对象…...

stm32利用CubeMX按键控制数码管加减数

首先画电路图&#xff1a; 接下来配置CubeMX&#xff1a; 设置好后生成MDK工程文件&#xff1a; 用keil打开工程&#xff1a; 添加部分代码&#xff1a; /* USER CODE BEGIN Includes */ uint16_t duan[]{0xC0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90}; uint1…...

前端页面生成条形码,借助layui打印标签

借助JsBarcode生成条形码 官网&#xff1a;https://lindell.me/JsBarcode/ github: https://github.com/lindell/JsBarcode <div class"table-div" style"display: block;width: 300px; height: 241px; margin: auto;"><table border"1&quo…...

第1~8章 综合复习

1. 重置root密码 1. 重启服务器&#xff08;虚拟机&#xff09;2. 快速选择第二项&#xff0c;然后按 e 键3. 在linux这一行的最后加上一个空格&#xff0c;然后输入 rd.break&#xff0c;然后按 ctrl x 来重启服务4. 在提示符所在位置输入 mount -o remount,rw /sysroot5. 在…...

转运机器人,AGV底盘小车:打造高效、精准的汽车电子生产线

为了满足日益增长的市场需求&#xff0c;保持行业领先地位&#xff0c;某汽车行业电子产品企业引入富唯智能AMR智能搬运机器人及其智能物流解决方案&#xff0c;采用自动化运输措施优化生产节拍和搬运效率&#xff0c;企业生产效率得到显著提升。 项目背景&#xff1a; 1、工厂…...

Spring Boot 的参数校验方案

1、前言 在平时的开发工作中,我们通常需要对接口进行参数格式验证。当参数个数较少(个数小于3)时,可以使用if ... else ...手动进行参数验证。当参数个数大于3个时,使用if ... else ...进行参数验证就会让代码显得臃肿,这个时候推荐使用注解来进行参数验证。 2、常用注…...

第N3周:Pytorch文本分类入门

>- **&#x1f368; 本文为[&#x1f517;365天深度学习训练营](https://mp.weixin.qq.com/s/rbOOmire8OocQ90QM78DRA) 中的学习记录博客** >- **&#x1f356; 原作者&#xff1a;[K同学啊 | 接辅导、项目定制](https://mtyjkh.blog.csdn.net/)** import torch import…...

宝塔面板安装了mysql5.7和phpMyadmin,但是访问phpMyadmin时提示502 Bad Gateway

操作流程截图如下&#xff1a; 原因是没有选择php版本 选择php版本 下一页找到phpMyAdmin&#xff0c;选择设置 目前只有纯净态&#xff0c;说明没有php环境&#xff0c;前去安装php环境 点击安装&#xff0c;选择版本&#xff0c;这里选择的是7.4版本&#xff0c;编译安…...

K8S—Pod详解

目录 一 Pod基础概念 1.1 Pod是什么 1.2 为什么要使用Pod&#xff1f;Pod在K8S集群中的使用方式&#xff1f; 1.3 基础容器pause 二 Pod的分类 2.1 自主式Pod和控制器管理的Pod 2.2 容器的分类 2.2.1 基础容器&#xff08;infrastructure container&#xff09; 2.2.2…...

深度学习中数据的转换

原始&#xff08;文本、音频、图像、视频、传感器等&#xff09;数据被转化成结构化且适合机器学习算法或深度学习模型使用的格式。 原始数据转化为结构化且适合机器学习和深度学习模型使用的格式&#xff0c;通常需要经历以下类型的预处理和转换&#xff1a; 文本数据&#xf…...

如何系统地自学 Python?

目录 Python 数据类型 控制结构 函数和模块 文件操作 异常处理 类和对象 列表推导式和生成器 匿名函数和高阶函数 面向对象编程 总结 Python Python是一种面向对象、解释型计算机程序设计语言&#xff0c;由Guido van Rossum于1989年发明&#xff0c;第一个公开发行…...

【软考】传输层协议之UDP

目录 一、说明二、特点 一、说明 1.用户数据报协议&#xff08;User Datagram Protocol&#xff09;是一种不可靠的、无连接的协议&#xff0c;可以保证应用程序进程间的通信 2.与TCP相比&#xff0c;UDP是一种无连接的协议&#xff0c;它的错误检测功能要弱很多 3.TCP有助于提…...

微服务-微服务链路追踪组件Skywalking实战

自动化监控系统Prometheus&Grafana实战&#xff1a; https://vip.tulingxueyuan.cn/detail/v_60f96e69e4b0e6c3a312c726/3?fromp_6006cac4e4b00ff4ed156218&type8&parent_pro_idp_6006d8c8e4b00ff4ed1569b2 APM-性能监控项目班&#xff1a; https://vip.tuling…...

Stream、Collections、Collectors用法

当涉及Java编程中的集合处理时&#xff0c;Stream、Collections和Collectors是三个常用的工具。以下是它们各自的主要功能和使用的一些方法的概要&#xff1a; Stream&#xff1a; 概要&#xff1a;Stream 是 Java 8 引入的一个强大工具&#xff0c;用于处理集合数据的流式操作…...

Jetson Xavier NX 与笔记本网线连接 ,网络共享,ssh连接到vscode

Jetson Xavier NX 与笔记本网线连接 &#xff0c;网络共享&#xff0c;ssh连接到vscode Jetson Xavier NX桌面版需要连接显示屏、鼠标和键盘&#xff0c;操作起来并不方便&#xff0c;因此常常需要ssh远程连接到本地笔记本电脑&#xff0c;这里介绍一种连接方式&#xff0c;通过…...

MFC内存泄露

1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...

在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module

1、为什么要修改 CONNECT 报文&#xff1f; 多租户隔离&#xff1a;自动为接入设备追加租户前缀&#xff0c;后端按 ClientID 拆分队列。零代码鉴权&#xff1a;将入站用户名替换为 OAuth Access-Token&#xff0c;后端 Broker 统一校验。灰度发布&#xff1a;根据 IP/地理位写…...

Java - Mysql数据类型对应

Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...

多模态大语言模型arxiv论文略读(108)

CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题&#xff1a;CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者&#xff1a;Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...

Python 包管理器 uv 介绍

Python 包管理器 uv 全面介绍 uv 是由 Astral&#xff08;热门工具 Ruff 的开发者&#xff09;推出的下一代高性能 Python 包管理器和构建工具&#xff0c;用 Rust 编写。它旨在解决传统工具&#xff08;如 pip、virtualenv、pip-tools&#xff09;的性能瓶颈&#xff0c;同时…...

在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案

这个问题我看其他博主也写了&#xff0c;要么要会员、要么写的乱七八糟。这里我整理一下&#xff0c;把问题说清楚并且给出代码&#xff0c;拿去用就行&#xff0c;照着葫芦画瓢。 问题 在继承QWebEngineView后&#xff0c;重写mousePressEvent或event函数无法捕获鼠标按下事…...

MySQL 知识小结(一)

一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库&#xff0c;分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷&#xff0c;但是文件存放起来数据比较冗余&#xff0c;用二进制能够更好管理咱们M…...

Mysql8 忘记密码重置,以及问题解决

1.使用免密登录 找到配置MySQL文件&#xff0c;我的文件路径是/etc/mysql/my.cnf&#xff0c;有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...

Linux 中如何提取压缩文件 ?

Linux 是一种流行的开源操作系统&#xff0c;它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间&#xff0c;使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的&#xff0c;要在 …...

uniapp手机号一键登录保姆级教程(包含前端和后端)

目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号&#xff08;第三种&#xff09;后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...