【Rust光年纪】并发编程利器:探索 Rust 异步库与并行处理工具
构建高效异步应用:Rust 异步库详细解读
前言
在当今软件开发领域,Rust语言作为一种快速、安全和并发性能出色的编程语言,备受开发者青睐。随着Rust生态系统的不断扩大,越来越多的异步库和并行处理工具被引入到Rust开发中。本文将重点介绍几个在Rust语言中广泛应用的异步库和数据并行处理工具,这些工具可以帮助开发者更加高效地利用多核处理器,并实现安全、高性能的消息传递和共享数据操作。
欢迎订阅专栏:Rust光年纪
文章目录
- 构建高效异步应用:Rust 异步库详细解读
- 前言
- 1. rayon:一个数据并行库
- 1.1 简介
- 1.1.1 核心功能
- 1.1.2 使用场景
- 1.2 安装与配置
- 1.2.1 安装指南
- 1.2.2 基本配置
- 1.3 API 概览
- 1.3.1 并行迭代
- 1.3.2 数据并行操作
- 2. crossbeam:用于多消费多生产环境中的发送技术库
- 2.1 简介
- 2.1.1 核心功能
- 2.1.2 使用场景
- 2.2 安装与配置
- 2.2.1 安装指南
- 2.2.2 基本配置
- 2.3 API 概览
- 2.3.1 多消费者、多生产者通道
- 2.3.2 并发原语
- 3. tokio-postgres:一个用于Rust语言的异步PostgreSQL客户端
- 3.1 简介
- 3.1.1 核心功能
- 3.1.2 使用场景
- 3.2 安装与配置
- 3.2.1 安装指南
- 3.2.2 基本配置
- 3.3 API 概览
- 3.3.1 异步连接管理
- 3.3.2 异步数据操作
- 4. async-std:一个用于Rust语言的异步标准库
- 4.1 简介
- 4.1.1 核心功能
- 4.1.2 使用场景
- 4.2 安装与配置
- 4.2.1 安装指南
- 4.2.2 基本配置
- 4.3 API 概览
- 4.3.1 异步任务管理
- 4.3.2 异步I/O操作支持
- 5. async-graphql:一个用于构建GraphQL服务器的异步库
- 5.1 简介
- 5.1.1 核心功能
- 5.1.2 使用场景
- 5.2 安装与配置
- 5.2.1 安装指南
- 5.2.2 基本配置
- 5.3 API 概览
- 5.3.1 异步GraphQL解析
- 6. shellexpand:用于扩展环境变量和用户目录的路径的库
- 6.1 简介
- 6.1.1 核心功能
- 6.1.2 使用场景
- 6.2 API 概览
- 6.2.1 路径扩展
- 6.2.2 自定义变量扩展
- 总结
1. rayon:一个数据并行库
Rayon 是一个 Rust 语言的数据并行库,旨在提供数据并行操作的能力,以便更高效地利用多核处理器。
1.1 简介
1.1.1 核心功能
Rayon 的核心功能是提供数据并行操作的能力,能够将任务自动分配给可用的处理器核心,并通过适当的线程池管理来执行这些任务。
1.1.2 使用场景
Rayon 适用于需要并行处理大规模数据集的场景,如数据处理、图像处理等。通过 Rayon,可以轻松地编写并行化代码,充分利用多核处理器的计算能力。
1.2 安装与配置
1.2.1 安装指南
要使用 Rayon 库,首先需要在 Cargo.toml 文件中添加 Rayon 的依赖项:
[dependencies]
rayon = "1.5"
引入相应模块:
use rayon::prelude::*;
1.2.2 基本配置
Rayon 的基本配置包括线程池大小、任务分发策略等参数。一般情况下,不需要手动配置,Rayon 会根据当前系统和运行时环境进行自动调优。
1.3 API 概览
1.3.1 并行迭代
Rayon 提供了 par_iter 方法,可以对集合进行并行迭代操作。下面是一个简单的示例:
fn main() {let mut vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];vec.par_iter_mut().for_each(|x| *x += 1);println!("{:?}", vec);
}
通过 par_iter_mut 方法,可以对向量中的每个元素进行并行修改,提高了处理速度。
1.3.2 数据并行操作
除了并行迭代外,Rayon 还支持数据并行的 map、filter、reduce 等操作。下面是一个使用 Rayon 进行数据并行 map 操作的示例:
fn main() {let mut vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];let result: Vec<i32> = vec.par_iter().map(|x| x * 2).collect();println!("{:?}", result);
}
在上面的示例中,Rayon 的 par_iter 方法使得对向量中的每个元素进行乘法操作可以并行进行,提高了处理效率。
更多关于 Rayon 的信息,可以访问官方网站:Rayon
2. crossbeam:用于多消费多生产环境中的发送技术库
2.1 简介
2.1.1 核心功能
crossbeam 是一个 Rust 语言下的并发库,提供了多种并发原语和工具,支持在多消费者和多生产者环境下进行安全的消息传递和共享数据操作。
2.1.2 使用场景
适用于需要在多线程环境下进行消息传递和共享数据操作的场景,如并发队列、通道等。
2.2 安装与配置
2.2.1 安装指南
在 Cargo.toml 中添加 crossbeam 的依赖项:
[dependencies]
crossbeam = "0.8"
在代码中引入 crossbeam 模块即可开始使用。
2.2.2 基本配置
可以根据需求选择合适的并发原语和工具,进行相应的配置和使用。
2.3 API 概览
2.3.1 多消费者、多生产者通道
crossbeam 提供了 mpmc::channel 方法,用于创建多消费者、多生产者通道。以下是一个简单的示例:
use crossbeam::channel;fn main() {let (s, r) = channel::unbounded();for i in 0..10 {let s = s.clone();std::thread::spawn(move || {s.send(i).unwrap();});}for _ in 0..10 {println!("Received: {}", r.recv().unwrap());}
}
官网链接:crossbeam
2.3.2 并发原语
crossbeam 支持多种并发原语,如 Mutex、RwLock 等,用于安全地共享数据。以下是一个使用 Mutex 的示例:
use std::sync::{Arc, Mutex};
use std::thread;fn main() {let data = Arc::new(Mutex::new(0));let mut handles = vec![];for _ in 0..10 {let data = Arc::clone(&data);let handle = thread::spawn(move || {let mut data = data.lock().unwrap();*data += 1;});handles.push(handle);}for handle in handles {handle.join().unwrap();}println!("Result: {:?}", data.lock().unwrap());
}
官网链接:crossbeam
3. tokio-postgres:一个用于Rust语言的异步PostgreSQL客户端
3.1 简介
tokio-postgres 是一个为 Rust 语言设计的异步 PostgreSQL 客户端。它建立在 Tokio 框架之上,提供了高效的异步操作方式,并且具有强大的功能和灵活的配置选项。
3.1.1 核心功能
- 提供异步连接管理
- 支持异步数据操作
- 支持复杂的查询和事务管理
- 提供了对 Postgres 数据库的全面访问能力
3.1.2 使用场景
tokio-postgres 适用于需要在 Rust 项目中使用 PostgreSQL 数据库,并且希望利用异步编程模式来提高并发性能的开发场景。
3.2 安装与配置
3.2.1 安装指南
要在 Rust 项目中使用 tokio-postgres,首先需要在项目的 Cargo.toml 文件中添加 tokio-postgres 的依赖:
[dependencies]
tokio-postgres = "0.7"
然后在代码中引入 tokio-postgres 库:
extern crate tokio_postgres;
3.2.2 基本配置
在使用 tokio-postgres 之前,需要确保已经正确配置了 PostgreSQL 数据库,并且拥有相应的连接信息(如数据库地址、用户名、密码等)。
3.3 API 概览
3.3.1 异步连接管理
tokio-postgres 提供了异步连接管理的功能,可以通过 tokio_postgres::connect 方法来建立异步连接,并且可以使用 .await 方法等待连接的建立完成。
use tokio_postgres::{NoTls, Error};#[tokio::main]
async fn main() -> Result<(), Error> {let (client, connection) = tokio_postgres::connect("host=localhost user=postgres dbname=mydb",NoTls,).await?;tokio::spawn(async move {if let Err(e) = connection.await {eprintln!("connection error: {}", e);}});// 使用 client 进行数据库操作Ok(())
}
详细的异步连接管理方法可以参考 tokio-postgres 官方文档
3.3.2 异步数据操作
一旦建立了异步连接,就可以使用 tokio-postgres 进行异步数据操作,比如执行 SQL 查询、更新数据等操作。
use tokio_postgres::{NoTls, Error};#[tokio::main]
async fn main() -> Result<(), Error> {let (client, connection) = tokio_postgres::connect("host=localhost user=postgres dbname=mydb",NoTls,).await?;tokio::spawn(async move {if let Err(e) = connection.await {eprintln!("connection error: {}", e);}});let rows = client.query("SELECT id, name FROM users", &[]).await?;for row in &rows {let id: i32 = row.get(0);let name: &str = row.get(1);println!("id: {}, name: {}", id, name);}Ok(())
}
更多异步数据操作的方法可以查阅 tokio-postgres 官方文档
4. async-std:一个用于Rust语言的异步标准库
4.1 简介
async-std 是一个用于 Rust 语言的异步标准库,它提供了丰富的功能来简化异步编程。通过 async-std,开发者可以轻松地创建和管理异步任务以及进行异步I/O操作。
4.1.1 核心功能
- 异步任务管理
- 异步I/O操作支持
4.1.2 使用场景
async-std 可以应用于需要处理大量并发任务或进行高效的异步I/O操作的场景,例如网络编程、Web 服务等。
4.2 安装与配置
4.2.1 安装指南
要开始使用 async-std,首先需要在项目的 Cargo.toml 文件中添加以下依赖:
[dependencies]
async-std = "1.8"
然后执行以下命令安装 async-std:
$ cargo build
4.2.2 基本配置
在 Rust 项目中引入 async-std 库后,就可以开始使用其中提供的异步功能。
4.3 API 概览
4.3.1 异步任务管理
async-std 提供了一套完善的异步任务管理 API,开发者可以使用 async 和 await 关键字来定义和管理异步任务。
例如,下面是一个简单的异步任务示例:
use async_std::task;async fn hello_async() {println!("Hello, async!");
}fn main() {task::block_on(async {hello_async().await;});
}
更多关于异步任务管理的内容,请参考 async-std 的官方文档。
4.3.2 异步I/O操作支持
async-std 提供了对异步I/O操作的全面支持,包括文件操作、网络通信等。开发者可以通过 async-std 轻松实现高效的异步I/O编程。
以下是一个简单的异步文件读取示例:
use async_std::fs::File;
use async_std::prelude::*;async fn read_file() -> std::io::Result<String> {let mut file = File::open("example.txt").await?;let mut contents = String::new();file.read_to_string(&mut contents).await?;Ok(contents)
}
有关异步I/O操作支持的更多信息,请查阅 async-std 的官方文档。
5. async-graphql:一个用于构建GraphQL服务器的异步库
5.1 简介
async-graphql 是一个用于构建GraphQL服务器的异步库,它提供了一种方便的方式来定义和执行GraphQL 模式。
5.1.1 核心功能
async-graphql 的核心功能包括:
- 异步执行GraphQL查询
- 支持GraphQL模式的定义与解析
- 异步数据加载器
- 自定义中间件
- 错误处理机制
5.1.2 使用场景
async-graphql 可以被广泛用于构建高性能的GraphQL服务器。它适用于Web服务、后端服务等各种异步应用场景。
5.2 安装与配置
5.2.1 安装指南
你可以在 Cargo.toml 文件中添加 async-graphql 作为依赖:
[dependencies]
async-graphql = "4.0"
然后使用 cargo build 命令来安装该库。
5.2.2 基本配置
基本配置包括创建 GraphQL 服务器和定义数据模型。以下是一个简单示例:
use async_graphql::{EmptyMutation, EmptySubscription, Object, Schema, SimpleObject};#[derive(SimpleObject)]
struct User {id: String,name: String,
}struct Query;#[Object]
impl Query {async fn user(&self, id: String) -> User {// 返回用户信息User {id,name: format!("User {}", id),}}
}#[tokio::main]
async fn main() {let schema = Schema::build(Query, EmptyMutation, EmptySubscription).finish();
}
5.3 API 概览
5.3.1 异步GraphQL解析
async-graphql 提供了异步执行GraphQL查询的能力。下面是一个简单的示例代码:
use async_graphql::{Context, EmptyMutation, EmptySubscription, Object, Schema, SimpleObject};// 定义数据模型
#[derive(SimpleObject)]
struct User {id: String,name: String,
}// 查询对象
struct Query;#[Object]
impl Query {async fn user(&self, id: String) -> User {// 返回用户信息User {id,name: format!("User {}", id),}}
}#[tokio::main]
async fn main() {// 创建并运行 GraphQL 服务器let schema = Schema::build(Query, EmptyMutation, EmptySubscription).finish();// 执行查询let query = r#"{user(id: "123") {idname}}"#;let result = schema.execute(query).await;println!("{:?}", result);
}
更多详情请参考 async-graphql官网。
6. shellexpand:用于扩展环境变量和用户目录的路径的库
6.1 简介
shellexpand 是一个用于扩展环境变量和用户目录路径的 Rust 库。它允许用户将包含环境变量或用户目录(如~)的路径字符串转换为绝对路径。
6.1.1 核心功能
shellexpand 的核心功能是扩展包含环境变量和用户目录的路径字符串,将其转换为实际的绝对路径,以便进行文件操作等操作。
6.1.2 使用场景
使用 shellexpand 可以方便地处理包含环境变量和用户目录的路径,使其能够被程序正确识别并使用。
6.2 API 概览
shellexpand 库提供了以下主要功能:
6.2.1 路径扩展
通过 shellexpand,可以将包含环境变量的路径字符串扩展为实际的绝对路径。下面是一个示例代码:
use shellexpand::tilde;fn main() {let path_str = "~/Documents/file.txt";let expanded_path = shellexpand::tilde(path_str);println!("Expanded Path: {}", expanded_path);
}
官网链接:shellexpand
6.2.2 自定义变量扩展
除了环境变量和用户目录的扩展外,shellexpand 还支持自定义变量的扩展。下面是一个示例代码:
use shellexpand::full_with_context;
use std::collections::HashMap;fn main() {let mut variables = HashMap::new();variables.insert("MY_DIR", "/path/to/my/directory");let path_str = "$MY_DIR/file.txt";let expanded_path = shellexpand::full_with_context(path_str, |var| {variables.get(var).map(|v| v.as_ref())});println!("Expanded Path: {}", expanded_path);
}
官网链接:shellexpand
通过以上示例代码,可以看到 shellexpand 提供了方便的方法来处理路径中的环境变量和自定义变量,使得路径处理更加灵活和便捷。
总结
通过本文的介绍,读者可以深入了解到在Rust语言中用于并行处理和异步编程的关键工具和库。这些工具和库不仅能够帮助开发者更好地利用硬件资源,提高程序的性能和并发能力,同时也能够简化异步编程的复杂性,提升开发效率。对于需要处理大规模数据集、构建高性能异步应用或构建GraphQL服务器的开发者来说,本文介绍的内容将会是非常有益的。
相关文章:
【Rust光年纪】并发编程利器:探索 Rust 异步库与并行处理工具
构建高效异步应用:Rust 异步库详细解读 前言 在当今软件开发领域,Rust语言作为一种快速、安全和并发性能出色的编程语言,备受开发者青睐。随着Rust生态系统的不断扩大,越来越多的异步库和并行处理工具被引入到Rust开发中。本文将…...
机器学习第一课
1.背景 有监督学习:有标签(连续变量(回归问题:时间序列等)、分类变量(分类)) 无监督学习:没有标签(聚类、关联(相关性分析:哪些相关…...
C语言典型例题32
《C程序设计教程(第四版)——谭浩强》 习题2.9 编程序用getchar函数读入两个字符给c1,c2,然后分别用putchar函数和printf函数输出这两个字符。 (1)变量c1,c2应该定义为字符型或者整型吗&#x…...
第二十五天学习笔记2024.8.9
1、通过frp内网穿透共享数据库信息 [root1 ~]# mysql -p密码 mysql> create user li% identified by 1; mysql> create database test; mysql> grant all on test.* to li; [root1 ~]# tar -xf frp_0.33.0_linux_amd64.tar.gz [root1 ~]# cd frp_0.33.0_linux_a…...
sqlserver将一张表导出成txt
bcp zjwb_sb_20111122.dbo.ep_pb_groupvisitplace out c:/1.txt -n -U sa -P sa...
YOLOv8+DeepSort实现
目录 1,YOLOv8算法简介 2,DeepSort算法介绍 1. SORT目标追踪 3,实现流程 1.检测 2. 生成detections 3. 卡尔曼滤波预测 4.使用匈牙利算法将预测后的tracks和当前帧中的detections进行匹配 5. 卡尔曼滤波更新 4,代码实现 …...
「链表」链表原地算法合集:原地翻转|原地删除|原地取中|原地查重 / LeetCode 206|237|2095|287(C++)
概述 对于一张单向链表,我们总是使用双指针实现一些算法逻辑,这旨在用常量级别空间复杂度和线性时间复杂度来解决一些问题。 所谓原地算法,是指不使用额外空间的算法。 现在,我们利用双指针实现以下四种行为。 //Definition fo…...
【STM32】SPI通信和RTC实时时钟
个人主页~ SPI通信和RTC实时时钟 SPI通信一、简介二、硬件电路三、基本原理四、SPI时序1、时序基本单元2、时序 五、FLASH操作注意事项1、写入操作2、读取操作 六、SPI外设1、简介2、结构 七、传输方式1、主模式全双工连续传输2、非连续传输 RTC实时时钟一、Unix时间戳二、BKP1…...
DAMA学习笔记(十三)-大数据和数据科学
1.引言 大数据不仅指数据的量大,也指数据的种类多(结构化的和非结构化的,文档、文件、音频、视频、流数据等),以及数据产生的速度快。数据科学家是指从从数据中探究、研发预测模型、机器学习模型、规范性模型和分析方法…...
【Java】Java 中的 toLowerCase() 方法详解
我最爱的那首歌最爱的angel 我到什么时候才能遇见我的angel 我最爱的那首歌最爱的angel 我不是王子也会拥有我的angel 🎵 张杰《云中的angel》 在 Java 编程中,字符串处理是一个非常常见的任务。为了便于开发者操作和格式化字符串&…...
Linux: 进程概念详解
1. 冯诺依曼体系结构 截至目前,我们所认识的计算机,都是有一个个的硬件组件组成 。 【注意】: a. 这里的存储器指的是内存 b. 不考虑缓存情况,这里的CPU能且只能对内存进行读写,不能访问外设(输入或输出设备) c.外…...
【C++】模板详细讲解(含反向迭代器)
欢迎来到我的Blog,点击关注哦💕 前言: C的模板在是泛型编程的重要组成部分,编写在不同类型上工作的代码,而无需为每个类型编写重复的代码,这有助于减少代码冗余并提高代码的可维护性。 模板 模板的介绍 …...
haproxy七层代理详解之-完整安装部署流程及负载均衡实现-及热更新方法
一.负载均衡 1.1负载均衡时什么 负载均衡:Load Balance,简称LB,是一种服务或基于硬件设备等实现的高可用反向代理技术,负载均网络流量等)分担给指定的一个或多个后端特定的服务器或设备,从而提高了衡将特定的业务(web服务、公司…...
C++11 bind
bind bind 用来将可调用对象和参数一起进行绑定。可调用对象包括普通函数、全局函 数、静态函数、类静态函数甚至是类成员函数,参数包括普通参数和类成员。绑定后的 结果,可以使用 std::function 进行保存,并延迟调用到我们需要的时候。 绑…...
LeetCode199 二叉树的右视图
前言 题目: 199. 二叉树的右视图 文档: 代码随想录——二叉树的右视图 编程语言: C 解题状态: 成功解决! 思路 二叉树层序遍历问题的变种,右视图即意味着二叉树每层的最后一个节点。 代码 /*** Definiti…...
数据赋能(172)——开发:数据挖掘——影响因素、直接作用、主要特征
影响因素 主要影响因素如下: 数据类型与属性: 数据类型和对象的不同属性会使用不同的数据类型来描述,如年龄可能是整数类型,而生日则是日期类型。数据挖掘时需要对不同的数据类型进行不同的处理,这直接影响到挖掘算法…...
Vue:Vue3-TypeScript-Pinia-Vite-pnpm / 基础项目 / 20240807
一、项目技术栈 / 依赖 序号技术栈版本解释1node20.14.02vue 3.4.31 3vite 5.3.4 4TypeScript 5.2.2 5 types/node 22.0.2 解决TypeScript项目中缺少对应模块的类型定义文件的问题6 element-plus 2.7.8 ui组建7 types/js-cookie js-cookie 3.0.6 3.0.5 8 sass 1.77.8 9 hu…...
windows Qt 录屏 录音
启动录屏录音: connect(&m_Process, &QProcess::readyReadStandardOutput, [&]() {qDebug() << "Standard output:" << QString::fromLocal8Bit(m_Process.readAllStandardOutput()); });connect(&m_Process, &QProcess…...
AAC中的ADTS格式分析
😎 作者介绍:欢迎来到我的主页👈,我是程序员行者孙,一个热爱分享技术的制能工人。计算机本硕,人工制能研究生。公众号:AI Sun(领取大厂面经等资料),欢迎加我的…...
iOS内存管理---MRC vs ARC
系列文章目录 iOS基础—Block iOS基础—Protocol iOS基础—KVC vs KVO iOS网络—AFNetworking iOS网络—NSURLSession iOS内存管理—MRC vs ARC iOS基础—Category vs Extension iOS基础—多线程:GCD、NSThread、NSOperation iOS基础—常用三方库:Mason…...
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...
阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...
Mac软件卸载指南,简单易懂!
刚和Adobe分手,它却总在Library里给你写"回忆录"?卸载的Final Cut Pro像电子幽灵般阴魂不散?总是会有残留文件,别慌!这份Mac软件卸载指南,将用最硬核的方式教你"数字分手术"࿰…...
PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...
零基础设计模式——行为型模式 - 责任链模式
第四部分:行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习!行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想:使多个对象都有机会处…...
JDK 17 新特性
#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持,不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的ÿ…...
Pinocchio 库详解及其在足式机器人上的应用
Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库,专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性,并提供了一个通用的框架&…...
安卓基础(aar)
重新设置java21的环境,临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的: MyApp/ ├── app/ …...
C++使用 new 来创建动态数组
问题: 不能使用变量定义数组大小 原因: 这是因为数组在内存中是连续存储的,编译器需要在编译阶段就确定数组的大小,以便正确地分配内存空间。如果允许使用变量来定义数组的大小,那么编译器就无法在编译时确定数组的大…...
PostgreSQL——环境搭建
一、Linux # 安装 PostgreSQL 15 仓库 sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-$(rpm -E %{rhel})-x86_64/pgdg-redhat-repo-latest.noarch.rpm# 安装之前先确认是否已经存在PostgreSQL rpm -qa | grep postgres# 如果存在࿰…...
