数据库SQLite的使用

      SQLite是一个C语言库,实现了一个小型、快速、独立、高可靠性、功能齐全的SQL数据库引擎SQLite文件格式稳定、跨平台且向后兼容。SQLite源代码属于公共领域(public-domain),任何人都可以免费将其用于任何目的。源码地址:https://github.com/sqlite/sqlite,最新发布版本为3.47.0。

      SQLite是关系型数据库,与许多其它数据库管理系统不同,SQLite不是一个客户端/服务器结构的数据库引擎,而是被集成在用户程序中。SQLite将整个数据库,包括定义、表、索引以及数据本身,作为一个单独的、可跨平台使用的文件存储在主机中

      SQLite提供了一个叫做sqlite3的独立程序用来查询和管理SQLite数据库文件,可从 https://www.sqlite.org/download.html 下载sqlite-tools-win-x64-3470000.zip获取到。

      所有的SQLite语句可以以任何关键字开始,如SELECT、INSERT、UPDATE、DELETE、ALTER、DROP等,所有的语句通常使用分号;结束

      Windows10上生成SQLite静态库:

      (1).从 https://www.sqlite.org/download.html 下载sqlite-dll-win-x64-3470000.zip和sqlite-amalgamation-3470000.zip

      (2).解压缩到同一目录下:此目录下有sqlite3.dll、sqlite3.def、sqlite3.h、sqlite3.c、sqlite3ext.h、shell.c

      (3).打开"Developer Command Prompt for VS 2022",并将其定位到存放sqlite的目录下,执行如下命令:执行完后会生成sqlite3.lib和sqlite3.exp

lib /DEF:sqlite3.def /OUT:sqlite3.lib /MACHINE:x64

      SQLite开源的可视化工具DB Browser for SQLite(DB4S)的使用:

      1.SQLite数据库浏览器(DB4S)是一款高质量、可视化、开源工具,用于创建、设计和编辑与SQLite兼容的数据库文件。源码地址:https://github.com/sqlitebrowser/sqlitebrowser,license为GPL或类似的开源许可证,最新发布版本为v3.13.1。它是跨平台的,可在Windows、Linux、MacOS等操作系统上使用。DB4S操作:

      (1).创建和压缩数据库文件

      (2).创建、定义、修改和删除表

      (3).创建、定义和删除索引

      (4).浏览、编辑、添加和删除记录(records)

      (5).搜索记录

      (6).以文本形式导入和导出记录

      (7).从CSV文件导入和导出表

      (8).从SQL转储文件(dump files)导入和导出数据库

      (9).SQL查询并检查结果

      2.Windows10上安装DB4S:

      (1).从https://github.com/sqlitebrowser/sqlitebrowser/releases/tag/v3.13.1 下载DB.Browser.for.SQLite-v3.13.1-win64.zip,并解压缩

      (2).双击打开DB Browser for SQLite.exe即可:界面如下:

     

      (1).SQLite是不区分大小写的,但也有一些命令是大小写敏感的。

      (2).SQLite没有一个单独的用于存储日期和/或时间的存储类,但SQLite能够把日期和时间存储为TEXT、REAL或INTEGER值。

      (3).在对当前数据库进行操作(c++)前,需要先关闭DB4S。

      (4).DB4S没有刷新功能,而PostgreSQL的图形界面(pgAdmin 4)有。

      以下为测试代码段

      (1).创建数据库:

int create_database(const std::string& dbname)
{sqlite3* db{ nullptr };auto ret = sqlite3_open(dbname.c_str(), &db); // 如果数据库不存在,则会创建它if (ret != SQLITE_OK)std::cerr << "Error: fail to sqlite3_open: " << ret << ", " << sqlite3_errmsg(db) << std::endl;sqlite3_close(db);return ret;
}

      (2).删除数据库:直接调用C++17中的std::filesystem::remove函数删除类似*.db的文件

int delete_database(const std::string& dbname)
{namespace fs = std::filesystem;fs::path file{ dbname };if (fs::exists(file)) {try {fs::remove(file);}catch (const fs::filesystem_error& e) {std::cerr << "Error: " << e.what() << std::endl;return -1;}} else {std::cerr << "Warning: database file does not exist: " << dbname << std::endl;return -1;}return 0;
}

      (3).创建表:

int create_table(const std::string& dbname, const std::string& command)
{sqlite3* db{ nullptr };auto ret = sqlite3_open(dbname.c_str(), &db);if (ret != SQLITE_OK)std::cerr << "Error: fail to sqlite3_open: " << ret << ", " << sqlite3_errmsg(db) << std::endl;char* errmsg{ nullptr };ret = sqlite3_exec(db, command.c_str(), nullptr, nullptr, &errmsg);if (ret != SQLITE_OK) {std::cerr << "Error: fail to create table: " << ret << ", " << errmsg << std::endl;sqlite3_free(errmsg);}sqlite3_close(db);return ret;
}

      (4).删除表:

int drop_table(const std::string& dbname, const std::string& tablename)
{sqlite3* db{ nullptr };auto ret = sqlite3_open(dbname.c_str(), &db);if (ret != SQLITE_OK)std::cerr << "Error: fail to sqlite3_open: " << ret << ", " << sqlite3_errmsg(db) << std::endl;char* errmsg{ nullptr };const std::string str{ "DROP TABLE " };ret = sqlite3_exec(db, (str+tablename).c_str(), nullptr, nullptr, &errmsg);if (ret != SQLITE_OK) {std::cerr << "Error: fail to drop table: " << ret << ", " << errmsg << std::endl;sqlite3_free(errmsg);}sqlite3_close(db);return ret;
}

      (5).向表中插入数据:

int insert_into_teacher(const std::string& dbname, int id, const std::string& name, const std::string& addr, const std::string& sex)
{sqlite3* db{ nullptr };auto ret = sqlite3_open(dbname.c_str(), &db);if (ret != SQLITE_OK)std::cerr << "Error: fail to sqlite3_open: " << ret << ", " << sqlite3_errmsg(db) << std::endl;char* errmsg{ nullptr };std::string str{ "INSERT INTO teacher (id, name, addr, sex) VALUES (" };str = str + std::to_string(id) + ", '" + name + "', '" + addr + "', '" + sex + "');";ret = sqlite3_exec(db, str.c_str(), nullptr, nullptr, &errmsg);if (ret != SQLITE_OK) {std::cerr << "Error: fail to insert into teacher: " << ret << ", " << errmsg << std::endl;sqlite3_free(errmsg);}sqlite3_close(db);return ret;
}std::string get_current_time()
{auto timenow = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());std::tm* now_tm = std::localtime(&timenow);std::ostringstream oss;oss << std::put_time(now_tm, "%Y-%m-%d %H:%M:%S");return oss.str();
}int insert_into_student(const std::string& dbname, int id, const std::string& name, const std::string& addr, int age,float score, const std::string& date, const std::string& sex)
{sqlite3* db{ nullptr };auto ret = sqlite3_open(dbname.c_str(), &db);if (ret != SQLITE_OK)std::cerr << "Error: fail to sqlite3_open: " << ret << ", " << sqlite3_errmsg(db) << std::endl;char* errmsg{ nullptr };std::string str{ "INSERT INTO student (id, name, addr, age, score, date, sex) VALUES (" };str = str + std::to_string(id) + ", '" + name + "', '" + addr + "'," + std::to_string(age) + "," +std::to_string(score) + ", '" + date + "', '" + sex + "'); ";ret = sqlite3_exec(db, str.c_str(), nullptr, nullptr, &errmsg);if (ret != SQLITE_OK) {std::cerr << "Error: fail to insert into student: " << ret << ", " << errmsg << std::endl;sqlite3_free(errmsg);}sqlite3_close(db);return ret;
}

      (6).向已有表中添加、删除列:

int alter_table(const std::string& dbname)
{sqlite3* db{ nullptr };auto ret = sqlite3_open(dbname.c_str(), &db);if (ret != SQLITE_OK)std::cerr << "Error: fail to sqlite3_open: " << ret << ", " << sqlite3_errmsg(db) << std::endl;char* errmsg{ nullptr };const std::string str{ "ALTER TABLE teacher " };const std::string str1{ "ADD COLUMN hobbies CHAR(64) DEFAULT swim;" };ret = sqlite3_exec(db, (str+str1).c_str(), nullptr, nullptr, &errmsg);if (ret != SQLITE_OK) {std::cerr << "Error: fail to add cloumn: " << ret << ", " << errmsg << std::endl;sqlite3_free(errmsg);}const std::string str2{ "DROP COLUMN addr;" };ret = sqlite3_exec(db, (str + str2).c_str(), nullptr, nullptr, &errmsg);if (ret != SQLITE_OK) {std::cerr << "Error: fail to drop column: " << ret << ", " << errmsg << std::endl;sqlite3_free(errmsg);}sqlite3_close(db);return ret;
}

      (7).删除表中数据:

int delete_table_data(const std::string& dbname)
{sqlite3* db{ nullptr };auto ret = sqlite3_open(dbname.c_str(), &db);if (ret != SQLITE_OK)std::cerr << "Error: fail to sqlite3_open: " << ret << ", " << sqlite3_errmsg(db) << std::endl;char* errmsg{ nullptr };const std::string str{ "DELETE FROM teacher WHERE id > 10000 OR sex='女';" };ret = sqlite3_exec(db, str.c_str(), nullptr, nullptr, &errmsg);if (ret != SQLITE_OK) {std::cerr << "Error: fail to delete data from teachar: " << ret << ", " << errmsg << std::endl;sqlite3_free(errmsg);}sqlite3_close(db);return ret;
}

      (8).调整表中已有数据:

int update_table_data(const std::string& dbname)
{sqlite3* db{ nullptr };auto ret = sqlite3_open(dbname.c_str(), &db);if (ret != SQLITE_OK)std::cerr << "Error: fail to sqlite3_open: " << ret << ", " << sqlite3_errmsg(db) << std::endl;char* errmsg{ nullptr };const std::string str1 = std::string("UPDATE teacher SET sex = 'man' WHERE sex = ") + "\'" + gbk_to_utf8("男") + "\';";ret = sqlite3_exec(db, str1.c_str(), nullptr, nullptr, &errmsg);if (ret != SQLITE_OK) {std::cerr << "Error: fail to update data from teachar: " << ret << ", " << errmsg << std::endl;sqlite3_free(errmsg);}const std::string str2 = std::string("UPDATE teacher SET sex = ") + "\'" + gbk_to_utf8("女") + "\'" + " WHERE sex = 'woman';";ret = sqlite3_exec(db, str2.c_str(), nullptr, nullptr, &errmsg);if (ret != SQLITE_OK) {std::cerr << "Error: fail to update data from teachar: " << ret << ", " << errmsg << std::endl;sqlite3_free(errmsg);}sqlite3_close(db);return ret;
}

      (9).查询表中数据:

int select_table_data(const std::string& dbname)
{sqlite3* db{ nullptr };auto ret = sqlite3_open(dbname.c_str(), &db);if (ret != SQLITE_OK)std::cerr << "Error: fail to sqlite3_open: " << ret << ", " << sqlite3_errmsg(db) << std::endl;const std::string query{ "SELECT * FROM student WHERE age >= 20 AND DATETIME(date) > DATETIME('2024-11-07 17:54:30');" };char* errmsg{ nullptr };sqlite3_stmt* stmt{ nullptr };ret = sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, 0);if (ret != SQLITE_OK) {std::cerr << "Error: fail to sqlite3_prepare_v2: " << ret << ", " << sqlite3_errmsg(db) << std::endl;return ret;}std::cout << "id\tname\taddr\tage\tscore\tdate\t\t\t\tsex" << std::endl;while (sqlite3_step(stmt) == SQLITE_ROW) {auto id = sqlite3_column_int(stmt, 0);auto name = utf8_to_gbk(std::string(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1))));auto addr = utf8_to_gbk(std::string(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 2))));auto age = sqlite3_column_int(stmt, 3);auto score = sqlite3_column_double(stmt, 4);auto date = std::string(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 5)));auto sex = utf8_to_gbk(std::string(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 6))));std::cout << id << "\t" << name << "\t" << addr << "\t" << age << "\t" << score << "\t"<< date << "\t\t" << sex << std::endl;}sqlite3_finalize(stmt);sqlite3_close(db);return ret;
}

      全局变量设置如下:

const std::string table_teacher{ "CREATE TABLE teacher (""id INTEGER PRIMARY KEY NOT NULL CHECK(id>1000),""name TEXT NOT NULL,""addr TEXT DEFAULT 'BeiJing',""sex TEXT NOT NULL);" };
const std::string table_student{ "CREATE TABLE student (""id INTEGER PRIMARY KEY NOT NULL,""name CHAR(32) NOT NULL,""addr CHAR(64) DEFAULT 'TianJin',""age INTEGER,""score REAL,""date CHAR(24),""sex CHAR(8) NOT NULL);" };

      SQLite中没有实现类似libpqxx中的set_client_encoding函数,如果表中数据有中文则会显示乱码,这里实现utf8和gbk之间的转换:

inline std::string gbk_to_utf8(const std::string& str)
{
#ifdef _MSC_VER// gbk to wcharauto len = ::MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, nullptr, 0);std::wstring wstr(len, 0);::MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, &wstr[0], len);// wchar to utf8len = ::WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, nullptr, 0, nullptr, nullptr);std::string u8str(len, 0);::WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, &u8str[0], len, nullptr, nullptr);u8str.pop_back(); // remove '\0'return u8str;
#elsereturn std::string{"Unimplemented"};
#endif
}inline std::string utf8_to_gbk(const std::string& u8str)
{
#ifdef _MSC_VER// utf8 to wcharauto len = ::MultiByteToWideChar(CP_UTF8, 0, u8str.c_str(), -1, nullptr, 0);std::wstring wstr(len, 0);::MultiByteToWideChar(CP_UTF8, 0, u8str.c_str(), -1, &wstr[0], len);// wchar to gbklen = ::WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, nullptr, 0, nullptr, nullptr);std::string str(len, 0);::WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, &str[0], len, nullptr, nullptr);str.pop_back(); // remove '\0' return str;
#elsereturn std::string{"Unimplemented"};
#endif
}

      主函数如下:

int test_sqlite()
{const std::string dbname{ "info.db" };//create_database(dbname);delete_database(dbname);create_table(dbname, table_teacher);create_table(dbname, table_student);//drop_table(dbname, "teacher");//drop_table(dbname, "student");insert_into_teacher(dbname, 1111, gbk_to_utf8("Tom"), gbk_to_utf8("HeBei"), gbk_to_utf8("man"));insert_into_teacher(dbname, 5555, gbk_to_utf8("Tom"), gbk_to_utf8("北京"), gbk_to_utf8("男"));insert_into_teacher(dbname, 2222, gbk_to_utf8("小张"), gbk_to_utf8("天津"), gbk_to_utf8("woman"));insert_into_teacher(dbname, 16625, gbk_to_utf8("小王"), gbk_to_utf8("Tianjin"), gbk_to_utf8("女"));insert_into_student(dbname, 8, gbk_to_utf8("小王"), gbk_to_utf8("HeBei"), 32, 88.8f, get_current_time(), gbk_to_utf8("男"));insert_into_student(dbname, 28, gbk_to_utf8("小何"), gbk_to_utf8("深圳"), 8, 22.22f, get_current_time(), gbk_to_utf8("女"));std::this_thread::sleep_for(std::chrono::minutes(1));insert_into_student(dbname, 29, gbk_to_utf8("Lucy"), gbk_to_utf8("北京"), 18, 22.22f, get_current_time(), gbk_to_utf8("woman"));insert_into_student(dbname, 33, gbk_to_utf8("Tom"), gbk_to_utf8("深圳"), 28, 22.22f, get_current_time(), gbk_to_utf8("woman"));insert_into_student(dbname, 18, gbk_to_utf8("小李"), gbk_to_utf8("上海"), 28, 66.6f, get_current_time(), gbk_to_utf8("女"));std::this_thread::sleep_for(std::chrono::seconds(5));insert_into_student(dbname, 48, gbk_to_utf8("Tom"), gbk_to_utf8("深圳"), 38, 22.22f, get_current_time(), gbk_to_utf8("woman"));alter_table(dbname);delete_table_data(dbname);update_table_data(dbname);select_table_data(dbname);return 0;
}

      执行结果如下:

      DB4S显示内容如下:

      GitHub:https://github.com/fengbingchun/Messy_Test

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

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

相关文章

【大模型】Spring AI Alibaba 对接百炼平台大模型使用详解

目录 一、前言 二、Spring AI概述 2.1 spring ai是什么 2.2 Spring AI 核心能力 2.3 Spring AI 应用场景 三、Spring AI Alibaba 介绍 3.1 Spring AI Alibaba 是什么 3.2 Spring AI Alibaba 核心特点 3.3 Spring AI Alibaba 应用场景 四、SpringBoot 对接Spring AI Al…

Java:HTTP/HTTPS

HTTP HTTP(全称"超文本传输协议")是一种应用最广泛的应用层协议; 文本=>字符串 超文本:可以传输文本,图片,语言等等其他的各种数据... HTTP各种应用场景: 1.使用浏览器打开网页; 2.打开手机APP; 3.后端程序,都是"分布式/微服务"体系结构; HTTPS可…

【Promise】JS 异步之宏队列与微队列

文章目录 1 原理图2 说明3 相关面试题3.1 面试题13.2 面试题23.3 面试题33.4 面试题4 1 原理图 2 说明 JS 中用来存储待执行回调函数的队列包含 2 个不同特定的队列&#xff1a;宏队列和微队列。宏队列&#xff1a;用来保存待执行的宏任务(回调)&#xff0c;比如&#xff1a;定…

用 Python 从零开始创建神经网络(二):第一个神经元的进阶

第一个神经元的进阶 引言1. Tensors, Arrays and Vectors&#xff1a;2. Dot Product and Vector Additiona. Dot Product &#xff08;点积&#xff09;b. Vector Addition &#xff08;向量加法&#xff09; 3. A Single Neuron with NumPy4. A Layer of Neurons with NumPy5…

【优选算法 — 滑动窗口】最大连续1的个数 将 x 减到0的最小操作数

最大连续1的个数 最大连续1的个数 题目描述 题目解析 给我们一个元素全是0或者1的数组&#xff0c;和一个整数 k &#xff0c;然后让我们在数组选出最多的 k 个0&#xff1b;这里翻转最多 k 个0的意思&#xff0c;是翻转 0 的个数< k&#xff0c;而不是一定要翻转 k …

各种排序分组

简易排序方法如下: public static void XX(){var circles Z.db.SelectEntities<Circle>();circles circles.OrderByDescending(x > x.Center.Y).ThenBy(x > x.Center.X).ToList();for (int i 0; i < circles.Count; i){DBText text new DBText() { Positi…

RK3288 android7.1 适配 ilitek i2c接口TP

一&#xff0c;Ilitek 触摸屏简介 Ilitek 提供多种型号的触控屏控制器&#xff0c;如 ILI6480、ILI9341 等&#xff0c;采用 I2C 接口。 这些控制器能够支持多点触控&#xff0c;并具有优秀的灵敏度和响应速度。 Ilitek 的触摸屏控制器监测屏幕上的触摸事件。 当触摸发生时&am…

DICOM图像知识:DICOM图像排序与坐标系解析

目录 引言 1. 概述 2. DICOM图像排序规则 2.1 Patient的Study按Study Date排序 2.2 Study的Series按Series Number排序 2.3 Series的SOP按Instance Number或Slice Location排序 2.3.1 Instance Number排序 2.3.2 Slice Location排序 2.3.3 使用Image Position (Patien…

Js — 定时器

有两种&#xff1a;setInterval 和 setTimeout 间隔时间单位为毫秒 setInterval 每隔指定的毫秒数重复执行一个函数或代码 开启定时器&#xff1a;setInterval(函数&#xff0c;间隔时间) 作用&#xff1a;每隔一段时间调用这个函数 注意&#xff1a;它不是立即执行&#x…

其他教程:如何设计一个App扫码登录功能,来实现免账号密码登录功能,仅供参考

–本次教程是给大家列举一下常见的扫码登录功能&#xff0c;小程序或app均可参考&#xff0c;如需更安全的模式可多次设计加工&#xff0c;本次只列举概念层面的实现方式

ChatGPT键盘快捷键(按ctrl + /呼出)

文章目录 ChatGPT键盘快捷键- 打开新聊天: Ctrl Shift O- 聚焦聊天输入: Shift Esc- 复制最后一个代码块: Ctrl Shift ;- 复制最后一个回复: Ctrl Shift C- 设置自定义指令: Ctrl Shift I- 切换边栏: Ctrl Shift S- 删除聊天: Ctrl Shift ⌫- 显示快捷方式: Ctrl …

AWTK-HarmonyOS NEXT 发布

AWTK 全称为 Toolkit AnyWhere&#xff0c;是 ZLG 倾心打造的一套基于 C 语言开发的 GUI 框架。旨在为用户提供一个功能强大、高效可靠、简单易用、可轻松做出炫酷效果的 GUI 引擎&#xff0c;支持跨平台同步开发&#xff0c;一次编程&#xff0c;到处编译&#xff0c;跨平台使…

【开发】Java的内存溢出

Java之内存溢出 Java之内存溢出 | OutOfMemoryError 我们都知道&#xff0c;在Java的世界里&#xff0c;由JVM管理着Java中的“垃圾对象”&#xff0c;也就是不被引用的对象&#xff1b;当一个对象不被其它对象引用的时候&#xff0c;该对象就会被垃圾回收器清理掉。但是在某些…

EasyExcel的AbstractColumnWidthStyleStrategy注入CellStyle不生效

设置背景色 CellStyle style workbook.createCellStyle();style.setFillForegroundColor(IndexedColors.RED.getIndex()); // 是设置前景色不是背景色style.setFillPattern(FillPatternType.SOLID_FOREGROUND)EasyExcel.writerTable(0).head(Head1.class).registerWriteHandl…

【51单片机】LED点阵屏 原理 + 使用

学习使用的开发板&#xff1a;STC89C52RC/LE52RC 编程软件&#xff1a;Keil5 烧录软件&#xff1a;stc-isp 开发板实图&#xff1a; 文章目录 LED点阵屏显示原理74HC595 编码LED点阵屏显示笑脸LED点阵屏显示动画 LED点阵屏 点阵屏在开发板的右上角&#xff0c;注意使用前需要…

深度学习-张量相关

一. 张量的创建 张量简介 张量是pytorch的基本数据结构 张量&#xff0c;英文为Tensor&#xff0c;是机器学习的基本构建模块&#xff0c;是以数字方式表示数据的形式。 例如&#xff0c;图像可以表示为形状为 [3, 224, 224] 的张量&#xff0c;这意味着 [colour_channels, h…

使用vite构建一个react网站,并部署到Netlify上

这篇教程中&#xff0c;我会教你如何用vite快速构建一个react网站&#xff0c;并把网站免费部署到Netlify上&#xff0c;让别人可以经由网址访问你的react网站。 1. 使用vite构建基础框架 npm create vitelatestcd vite-project npm install npm run dev2. 网站内容设计 3. 构…

Fastify Swagger:自动化API文档生成与展示

在现代软件开发中&#xff0c;API文档的生成和维护是一个不可或缺的环节。Fastify Swagger 是一个专为 Fastify 框架设计的插件&#xff0c;它能够自动生成符合 Swagger&#xff08;OpenAPI v2 或 v3&#xff09;规范的文档&#xff0c;从而帮助开发者轻松创建和维护API文档。本…

【网络原理】万字详解 UDP 和 TCP

&#x1f970;&#x1f970;&#x1f970;来都来了&#xff0c;不妨点个关注叭&#xff01; &#x1f449;博客主页&#xff1a;欢迎各位大佬!&#x1f448; 文章目录 1. UDP1.1 UDP 报文格式1.1.1 源端口/目的端口1.1.2 报文长度1.1.3 校验和 2. TCP2.1 TCP 报文结构2.2 TCP 特…

Go 中的泛型,日常如何使用

泛型从 go 的 1.18 开始支持 什么是泛型编程 在泛型出现之前&#xff0c;如果需要计算两数之和&#xff0c;可能会这样写&#xff1a; func Add(a, b int) int {returb a b } 这个很简单&#xff0c;但是只能两个参数都是 int 类型的时候才能调用 如果想要计算两个浮点数…