Rust 进阶学习
Rust 进阶学习
文章目录
- Rust 进阶学习
- 所有权
- 作用域
- 移动和克隆
- 涉及函数的所有权机制
- 涉及参数的所有权
- 涉及返回值的所有权
- 引用和租借
- 可变引用
- 枚举类
- 枚举成员的属性
- 枚举匹配
- 结构体
- 结构体方法
- 结构体关联函数
- 错误处理
- 不可恢复错误
- 可恢复错误
- Rust代码组织管理
- Module
- 默认的Module
- 引用Module
- Crate
- Package
- Rust面向对象
- trait(特性)
- 默认特性
- 小结
所有权
所有权规则:
- 每个值都有一个变量,这个变量称为所有者;
- 每个值同时只能有一个所有者;
- 当所有者超出作用域时,它在内存中对应的值会被删除。
作用域
最简单的就是函数内的变量,在函数体外无法使用,因为在函数体外变量已经被删除
fn demo_func(){let demo_var = 1;println!("{}", demo_var);//函数体内的变量可以使用
}
fn main() {demo_func();println!("demo_var: {}", demo_var);//超出作用域无法使用
}
移动和克隆
移动需要分两种情况讨论。
对于基础数据类型以及由基础数据类型构成的复合类型,都是保存在栈内存中的数据值,进行变量赋值时,会在内存中复制一个同样的值。
如:
fn main() {let x = 5;let y = x;println!("x: {}, y: {}", x, y);/* x: 5, y: 5 */
}
对于保存在堆中的值,变量赋值时,会进行“移动”。
如,对String变量进行变量间的赋值:
fn main() {let s1 = String::from("hello");let s2 = s1; println!("s2: {}", s2); // s2通过移动指向了字符串hello的内存,可以打印println!("s1: {}", s1); // s1 已经失效,编译报错。
}
s1赋值给s2后,因为任何值只有一个所有者,s1不能再指向hello字符串这个内存值,所以s1不再有效。即进行了所谓的“移动”。
如果想要实现变量值之间的复制,需用通过克隆。如:
fn main() {let s1 = String::from("hello");let s2 = s1.clone(); // 将hello字符串克隆一份,s2指向克隆后的内存println!("s2: {}", s2); // s2指向克隆后的hello字符串println!("s1: {}", s1);
}
通过克隆,在内存中生成了一份相同的值,让新的变量指向它,不会导致原有内存值所有权被剥夺。
涉及函数的所有权机制
涉及参数的所有权
对于堆中的变量值,所有权会跟随函数参数进行转移:
fn main() {let str = String::from("param");string_print(str);// 此处str已经无效,param字符串的所有权已经被转移到函数中print!("str: {}", str);
}fn string_print(str: String) {println!("{}", str);
}
基础数据类型变量值不会转移:
fn main() {let number = 10;number_print(number);println!("number: {}", number);
}
/* 输出:
number_print: 10
number: 10
*/fn number_print(num: i32) {println!("number_print: {}", num);
}
涉及返回值的所有权
当变量被函数当作返回值返回时,所有权也会转移:
fn main() {let s1 = return_string();println!("s1: {}", s1);
}fn return_string() -> String {let str = String::from("a string");return str;
}
来看一下更复杂的情况,返回函数参数:
fn main() {let s1 = return_string();println!("s1: {}", s1);// 字符串hello所有权从函数中移动到s1let return_str = return_string_from_param(s1);// 字符串hello所有权移入函数中,再从函数中移出// println!("s1: {}", s1);// 此处s1已经无效,之前的内存值已经其他所有者占用println!("return_str: {}", return_str);}fn return_string() -> String {let str = String::from("hello");return str;
}fn return_string_from_param(str: String) -> String {return str;
}
还是上面的原则,所有权会随函数参数移动,函数内的值也会随返回值移动。
引用和租借
引用不会占用所有权,通过引用可以访问变量值,但不能修改值。
fn main() {let str = String::from("hello");let str_reference = &str;//引用strprintln!("str: {}, str_reference: {}", str, str_reference);// str: hello, str_reference: hello// str_reference.push_str("world");// 报错,引用无法修改原有的值
}
引用可以理解为类似c指针指向。引用变量会指向变量本身,但变量值的所有权还是归原变量所有。通过引用访问变量值,是对所有权的“租借”。“租借”只能进行值访问,不能进行值修改。
引用指向的是变量本身,当变量失去内存值的所有权,导致无效时,引用也同样无效。如:
fn main() {let str = String::from("hello");// str获得hello字符串的所有权let str_reference = &str;//引用strlet str_replace = str;// hello字符串所有权被移动,str无效println!("str_replace: {}", str_replace);// println!("str_reference: {}", str_reference);//报错,引用指向的是str,str已经无效,引用也无效
}
最后一行关闭注释,编译时会报错,提示你变量已经被租借,无法再移动:
boys@server:~/rust_study/demo$ cargo runCompiling demo v0.1.0 (/home/boys/rust_study/demo)
error[E0505]: cannot move out of `str` because it is borrowed--> src/main.rs:4:23|
2 | let str = String::from("hello");// str获得hello字符串的所有权| --- binding `str` declared here
3 | let str_reference = &str;//引用str| ---- borrow of `str` occurs here
4 | let str_replace = str;// hello字符串所有权被移动,str无效| ^^^ move out of `str` occurs here
5 | println!("str_replace: {}", str_replace);
6 | println!("str_reference: {}", str_reference);//报错,引用指向的是str,str已经无效,引用也无效| ------------- borrow later used hereFor more information about this error, try `rustc --explain E0505`.
error: could not compile `demo` (bin "demo") due to previous error
可变引用
普通引用无法修改原有内存值,通过可变引用可以修改。需要加关键字 mut
。
fn main() {let mut str = String::from("hello ");// str是mut可变的let str_reference = &mut str;//可变引用strstr_reference.push_str("world");println!("str_reference: {}", str_reference);//str_reference: hello world
}
为了防止出现并发访问问题,可变引用不可以多重引用。如:
fn main() {let mut string = String::from("hello");let s1 = &mut string;let s2 = &mut string;println!("s1: {}, s2: {}", s1, s2);//此处打印会报错,不能进行多重可变引用
}
会提示:
cannot borrow `string` as mutable more than once at a time
不可变引用因为无法修改变量的内存值,是只读的,不会产生竞态,因此可以多重引用。
fn main() {let string = String::from("hello");let s1 = &string;let s2 = &string;println!("s1: {}, s2: {}", s1, s2);// 不可变引用因为只是读取了变量内存值,可以进行多重引用
}
可变引用和不可变引用不能同时使用。非常容易理解,因为可变引用可以修改内存值,这会导致竞态、并发访问问题。RUST中是不允许的。
枚举类
枚举是对某类事物可能情况的列举。使用enum关键字定义枚举。
如,枚举操作系统类型:
enum OperateSystem{Android,IOS,Linux,Unix,Windows,
}
打印枚举,需要添加宏:
#[derive(Debug)]
使用 {:?}
占位符格式化为字符串打印出来:
#[derive(Debug)]
enum OperateSystem{Android,IOS,Linux,Unix,Windows,
}
fn main() {let os = OperateSystem::Android;println!("the os is: {:?}", os);//the os is: Android
}
枚举成员的属性
rust中的枚举可以包含属性,属性可以是不同类型。如:
#[derive(Debug)]
enum Shape{Circle{ radius: f64},Rectangle{ width: f32, length: f32},
}
fn main() {let circle = Shape::Circle { radius: 3.0};println!("circle: {:?}", circle);let rectangle = Shape::Rectangle { width: 3.0, length: 4.0 };println!("rectangle: {:?}", rectangle);/* 打印输出: circle: Circle { radius: 3.0 }rectangle: Rectangle { width: 3.0, length: 4.0 }*/
}
上面代码定义了一个Shape形状枚举,有两个成员,分别是圆形和矩形。
圆形有一个半径(radius)属性,使用f64类型;
矩形有两个属性,分别是长度(length)和宽度(width),都使用f32类型。
枚举类成员的属性也可以是匿名的,如:
#[derive(Debug)]
enum Shape{Circle(f64),Rectangle(f32, f32),
}
fn main() {let circle = Shape::Circle(3.0);println!("circle: {:?}", circle);let rectangle = Shape::Rectangle(3.0, 4.0);println!("rectangle: {:?}", rectangle);/* 打印输出: circle: Circle(3.0)rectangle: Rectangle(3.0, 4.0)*/
}
枚举匹配
使用match语法进行匹配:
#[derive(Debug)]
enum Shape{Circle{ radius: f64},Rectangle{ width: f32, length: f32},
}
fn main() {let circle = Shape::Circle { radius: 3.0};let rectangle = Shape::Rectangle { width: 3.0, length: 4.0 };match circle {Shape::Circle { radius } => println!("circle radius: {}", radius),Shape::Rectangle { width, length } => println!("rectangle width: {}, length: {}", width, length)}
}
匿名属性也可以在match语句中临时设置一个参数名,如:
#[derive(Debug)]
enum Shape{Circle( f64 ),Rectangle( f32, f32),
}
fn main() {let circle = Shape::Circle(3.0);match circle {Shape::Circle(radius) => {println!("circle radius: {}", radius)},Shape::Rectangle(width, length) => {println!("rectangle width: {}, length: {}", width, length)},}
}
结构体
结构体方法
结构体方法的形式与函数一致,之所以叫结构体方法,是因为它的第一个参数是结构体本身的引用。
直接上例子:
struct Rectangle {width: f32,length: f32
}impl Rectangle {/* 使用impl为结构体添加方法 */fn get_area(&self) -> f32 {// 第1个参数是对结构体本身的引用return self.width*self.length}
}
fn main() {let rectangle = Rectangle { width: 3.0, length: 4.0 };let area = rectangle.get_area();println!("rectangle's area: {}", area);
}
&self参数只是在声明时需要添加,调用时不需要传入。
结构体关联函数
结构体关联函数不依赖于结构体实例。
与结构体方法的直观区别是,方法没有&self作为第1个参数的要求。
struct Rectangle {width: f32,length: f32
}impl Rectangle {/* 使用impl为结构体添加方法 */fn create_instance(width_set: f32, length_set: f32) -> Rectangle {Rectangle { width: width_set, length: length_set }}fn get_area(&self) -> f32 {// 第1个参数是对结构体本身的引用return self.width*self.length}
}
fn main() {let rectangle = Rectangle::create_instance(5.0, 6.0);let area = rectangle.get_area();println!("rectangle's area: {}", area);
}
错误处理
不可恢复错误
Rust中的不可恢复错误(Unrecoverable Error)指的是发生了无法正常处理的错误,比如数组越界、空指针解引用等。当程序遇到不可恢复错误时,会触发panic(恐慌)并终止程序的运行。
可以使用panic宏主动触发panic,如:
fn main() {panic!("just a test panic!");println!("can not run here.");
}
运行时会主动触发pianic来终止程序运行:
boys@server:~/rust_study/demo$ ./target/debug/demo
thread 'main' panicked at 'just a test panic!', src/main.rs:2:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
根据提示,加入RUST_BACKTRACE=1环境变量运行,可以追踪到panic发生的地方:
boys@server:~/rust_study/demo$ RUST_BACKTRACE=1 ./target/debug/demo
thread 'main' panicked at 'just a test panic!', src/main.rs:2:5
stack backtrace:0: rust_begin_unwindat /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/panicking.rs:578:51: core::panicking::panic_fmtat /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/panicking.rs:67:142: demo::mainat ./src/main.rs:2:53: core::ops::function::FnOnce::call_onceat /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/ops/function.rs:250:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
可恢复错误
可恢复错误指的是那些在运行时可以被程序处理和修复的错误,这些错误通常是可以预见和处理的。具体而言,可恢复错误可以包括但不限于以下情况:
- 文件操作错误 :如文件不存在、无法打开文件、读取或写入文件失败等。
- 网络通信错误 :如连接超时、服务器错误、网络断开等。
- 输入验证错误 :如用户输入不合法、缺少必要参数等。
- 数据库操作错误 :如查询失败、连接错误、事务回滚等。
- 外部资源错误 :如磁盘空间不足、内存耗尽等。
- 解析和转换错误 :如JSON解析错误、数据类型转换失败等。
- 并发操作错误 :如竞争条件、死锁等。
- 配置和环境错误 :如配置文件损坏、依赖缺失等。
可恢复错误与不可恢复错误(例如硬件故障、内存错误、空指针引用等)不同,后者通常无法在运行时被程序处理和修复,需要采取其他措施(如程序重启、报告错误给用户等)。
对于可恢复错误,使用Result类型可以提供一种良好的错误处理机制,使得程序能够检测到错误并根据需要采取适当的处理措施。如:
use std::{fs::File, error};fn main() {let fp = File::open("./file.txt");match fp {Result::Ok(file) => {println!("open {:?} success", file);},Result::Err(error) => {println!("open file fail: {}", error);}}
}
没有文件时会输出:
boys@server:~/rust_study/demo/target/debug$ ./demo
open file fail: No such file or directory (os error 2)
Rust代码组织管理
Rust 代码组织中有三个重要的概念:Crate(箱)、Package(包)、Module(模块)。
Module
Module(模块)类似于命名空间,用来管理代码的作用域。
使用mod关键字来定义一个Module,引用时使用符号 ::
下面是一个示例:
mod utility {pub fn print_num(num: i32){println!("{}", num);}
}fn main() {utility::print_num(33);
}
Module内的成员是有访问权限控制的,默认的访问权限是在Module内,要在Module外能引用,需要加入pub关键字声明,表明这个成员是public的。如:
mod utility {fn debug_print(num: i32) {println!("num = {}, hex: {:#x}", num, num);}pub fn print_num(num: i32){println!("{}", num);debug_print(num);// 只有内部才能使用}
}fn main() {utility::print_num(33);// utility::debug_print(33);/* module外使用会报错 */
}
Module内可以定义其他的Module,形成层次。如:
mod utility {pub mod printer{pub fn println(num: i32){println!("{}", num);}}pub mod calculator{pub fn get_numbers_sum(num1: i32, num2: i32) -> i32{num1+num2}}
}fn main() {let sum = utility::calculator::get_numbers_sum(1, 1);utility::printer::println(sum);
}
默认的Module
创建.rs文件时,就会产生一个与文件名同名的Module。如:
在ulitity.rs中代码如下:
pub mod printer{pub fn println(num: i32){println!("{}", num);}
}
pub mod calculator{pub fn get_numbers_sum(num1: i32, num2: i32) -> i32{num1+num2}
}
虽然我们没有使用mod关键字声明一个Module来包含这两个module,但默认已经使用了文件名作为默认的Module。
在main.rs中声明一下,即可调用:
mod utility;/* 声明Module */
fn main() {let sum = utility::calculator::get_numbers_sum(1, 1);utility::printer::println(sum);
}
引用Module
使用use关键字对一个Module或Module内的成员进行引用。如:
mod utility {pub mod printer{pub fn println(num: i32){println!("{}", num);}}pub mod calculator{pub fn get_numbers_sum(num1: i32, num2: i32) -> i32{num1+num2}}
}use utility::printer;/* 引用printer module */
use utility::calculator::get_numbers_sum;/* 引用calculator内的成员函数: get_numbers_sum */
fn main() {let sum = get_numbers_sum(1, 1);/* 使用时不用再注明前面的module */printer::println(sum);
}
Crate
Crate 是 Rust 的构建块,用于组织和管理代码,它可以包含一个或多个Module(模块)和其他项(如函数、结构体、枚举等)。
Crate可以分为2种类型:
- lib,即库类型Crate
- bin,即二进制Crate
库Crate可以生成库文件,给其他代码共享、复用,二进制Crate生成的是可执行文件。
通常情况下,Rust 项目的 Crate 遵循一种约定俗成的目录结构,有助于组织和管理代码。
以下是一个常见的 Rust 项目目录结构示例:
my_project/
├── src/ # 存放源代码
│ ├── main.rs # 二进制 Crate 的入口文件
│ └── lib.rs # 库 Crate 的入口文件
├── tests/ # 存放测试代码
├── examples/ # 存放示例代码
├── Cargo.toml # 描述包和依赖关系的文件
└── README.md # 项目文档
Package
Package(包)包含了Crate,可以同时包含多个Crate。但多个Crate里面只能有一个库Crate,可以有多个二进制Create。
Rust面向对象
trait(特性)
trait(特性)简单地说,就是一组通用的属性,当需要使用这些特性时,只需要通过impl关键字实现他们,即可拥有这些特性。
如:
trait Person{/* 定义一个关于Person的特性 */fn get_name(&self) -> &str;/* 获取姓名的接口 */
}
上面定义了一个Person的特性,特性包含一个获取姓名的接口。当需要获得这个特性时,即可通过impl关键字实现,如:
trait Person{/* 定义一个关于Person的特性 */fn get_name(&self) -> &str;/* 获取姓名的接口 */
}
struct XiaoMing{name: String,
}
struct ZhangSan{name: String
}impl Person for XiaoMing {/* 为xiaoming实现Person特性 */fn get_name(&self) -> &str {&self.name}
}
impl Person for ZhangSan {/* 为zhangsan实现Person特性 */fn get_name(&self) -> &str {&self.name}
}fn main() {let ming = XiaoMing{name: String::from("mingming"),};println!("xiaoming's name: {}", ming.get_name());let zhang = ZhangSan{name: String::from("zhangsan")};println!("zhang_san's name: {}", zhang.get_name());
}
默认特性
trait可以实现定义的接口,如果实现这个特性的类型没有对该接口覆盖,则调用这个接口时还是调用trait中默认接口。如:
trait Person{/* 定义一个关于Person的特性 */fn get_name(&self) -> &str;/* 获取姓名的接口 */fn tell_age(&self){/* 默认实现,未实现会调用此默认接口 */println!("unkown age");}
}
struct XiaoMing{name: String,
}
struct ZhangSan{name: String
}impl Person for XiaoMing {/* 为xiaoming实现Person特性 */fn get_name(&self) -> &str {&self.name}fn tell_age(&self){println!("xiaoming is 18 years old");}
}
impl Person for ZhangSan {/* 为zhangsan实现Person特性 */fn get_name(&self) -> &str {&self.name}
}fn main() {let ming = XiaoMing{name: String::from("mingming"),};ming.tell_age();let zhang = ZhangSan{name: String::from("zhangsan")};zhang.tell_age();/* 输出结果:xiaoming is 18 years oldunkown age*/
}
小结
train(特性)有点类似cpp中的虚函数和纯虚函数,没有实现的接口,在impl时必须实现。有默认实现的,如果impl未实现,则会调用默认的实现。
相关文章:
Rust 进阶学习
Rust 进阶学习 文章目录 Rust 进阶学习所有权作用域移动和克隆涉及函数的所有权机制涉及参数的所有权涉及返回值的所有权 引用和租借可变引用 枚举类枚举成员的属性枚举匹配 结构体结构体方法结构体关联函数 错误处理不可恢复错误可恢复错误 Rust代码组织管理Module默认的Modul…...

保护网站安全:学习蓝莲花的安装和使用,复现跨站脚本攻击漏洞及XSS接收平台
这篇文章旨在用于网络安全学习,请勿进行任何非法行为,否则后果自负。 环境准备 一、XSS基础 1、反射型XSS 攻击介绍 原理 攻击者通过向目标网站提交包含恶意脚本的请求,然后将该恶意脚本注入到响应页面中,使其他用户在查看…...

Redis——如何解决redis穿透、雪崩、击穿问题
目录 一、查询商品信息的常规代码示例二、缓存击穿2.1、缓存击穿的理解2.2、缓存击穿的解决方案2.3、解决缓存击穿的代码示例 三、缓存雪崩3.1、缓存雪崩的理解3.2、缓存雪崩的解决方案3.2.1、缓存集中过期的情况3.2.2、缓存服务器宕机的情况3.2.3、缓存服务器断电的情况 3.3、…...

MySQL一行记录是如何存储的?
目录 MySQL的数据存放在哪个文件? 表空间文件的结构是怎么样的? 1、行(row) 2、页(page) 3、区(extent) 4、段(segment) InnoDB 行格式有哪些…...
[element-ui] el-tree全部展开与收回
shrinkTreeNode () {// 改变一个全局变量this.treeStatus !this.treeStatus;// 改变每个节点的状态this.changeTreeNodeStatus(this.$refs.attrList.store.root); },// 改变节点的状态 changeTreeNodeStatus (node) {node.expanded this.treeStatus;for (let i 0; i < no…...

git 统计(命令)
查询某人某个时刻提交了多少代码 added 添加代码 removed 删除代码 total 总代码 git log --author刘俊秦 --since2023-08-01 00:00:00 --until2023-08-23 23:00:00 --prettytformat: --numstat | awk { add $1; subs $2; loc $1 - $2 } END { printf "added lines: %s…...
斐波那契1(矩阵快速幂加速递推,斐波那契前n项平方和)
链接:登录—专业IT笔试面试备考平台_牛客网 来源:牛客网 Keven 特别喜欢斐波那契数列,已知 fib11fib_11fib11,fib21fib_21fib21,对于 n>3n>3n>3,fibnfibn−2fibn−1fib_{n}fib_{n-2}fib_{n…...

minikube mac 启动
系统信息如下 最开始使用的minikube是1.22.0版本,按照如下命令启动: minikube start --memory7851 --cpus4 --image-mirror-countrycn遇到了下面一些问题: 1、拉取coredns:v1.8.0镜像失败 Error response from daemon: manifest for regis…...

从零开始学习 Java:简单易懂的入门指南之查找算法及排序算法(二十)
查找算法及排序算法 常见的七种查找算法:1. 基本查找2. 二分查找3. 插值查找4. 斐波那契查找5. 分块查找6. 哈希查找7. 树表查找 四种排序算法:1. 冒泡排序1.1 算法步骤1.2 动图演示1.3 代码示例 2. 选择排序2.1 算法步骤2.2 动图演示 3. 插入排序3.1 算…...

非煤矿山风险监测预警算法 yolov8
非煤矿山风险监测预警算法通过yolov8网络模型深度学习算法框架,非煤矿山风险监测预警算法在煤矿关键地点安装摄像机等设备利用智能化视频识别技术,能够实时分析人员出入井口的情况,人数变化并检测作业状态。YOLO的结构非常简单,就…...

Ansible学习笔记(一)
1.什么是Ansible 官方网站:https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html Ansible是一个配置管理和配置工具,类似于Chef,Puppet或Salt。这是一款很简单也很容易入门的部署工具,它使用SS…...

2024毕业设计选题指南【附选题大全】
title: 毕业设计选题指南 - 如何选择合适的毕业设计题目 date: 2023-08-29 categories: 毕业设计 tags: 选题指南, 毕业设计, 毕业论文, 毕业项目 - 如何选择合适的毕业设计题目 当我们站在大学生活的十字路口,毕业设计便成了我们面临的一项重要使命。这不仅是对我们…...

Error: PostCSS plugin autoprefixer requires PostCSS 8 问题解决办法
报错:Error: PostCSS plugin autoprefixer requires PostCSS 8 原因:autoprefixer版本过高 解决方案: 降低autoprefixer版本 执行:npm i postcss-loader autoprefixer8.0.0...
pymongo通过oplog获取数据(mongodb)
使用 MongoDB 的 oplog(操作日志)进行数据同步是高级的用法,主要用于复制和故障恢复。需要确保源 MongoDB 实例是副本集的一部分,因为只有副本集才会维护 oplog。 以下是简化的步骤,描述如何使用 oplog 进行数据同步&…...

MySQL数据备份与恢复
备份的主要目的: 备份的主要目的是:灾难恢复,备份还可以测试应用、回滚数据修改、查询历史数据、审计等。 日志: MySQL 的日志默认保存位置为: /usr/local/mysql/data##配置文件 vim /etc/my.cnf [mysqld] ##错误日志…...

基于ssm+vue汽车售票网站源码和论文
基于ssmvue汽车售票网站源码和论文088 开发工具:idea 数据库mysql5.7 数据库链接工具:navcat,小海豚等 技术:ssm 摘 要 互联网发展至今,无论是其理论还是技术都已经成熟,而且它广泛参与在社会中的方方面面。它让…...
【List】List集合有序测试案例:ArrayList,LinkedList,Vector(123)
List是有序、可重复的容器。 有序: List中每个元素都有索引标记。可以根据元素的索引标记(在List中的位置)访问 元素,从而精确控制这些元素。 可重复: List允许加入重复的元素。更确切地讲,List通常允许满足 e1.equals(e2) 的元素…...

【javaweb】学习日记Day6 - Mysql 数据库 DDL DML
之前学习过的SQL语句笔记总结戳这里→【数据库原理与应用 - 第六章】T-SQL 在SQL Server的使用_Roye_ack的博客-CSDN博客 目录 一、概述 1、如何安装及配置路径Mysql? 2、SQL分类 二、DDL 数据定义 1、数据库操作 2、IDEA内置数据库使用 (1&…...
使用 PyTorch C ++前端
使用 PyTorch C 前端 PyTorch C 前端是 PyTorch 机器学习框架的纯 C 接口。 虽然 PyTorch 的主要接口自然是 Python,但此 Python API 建立于大量的 C 代码库之上,提供基本的数据结构和功能,例如张量和自动微分。 C 前端公开了纯 C 11 API&a…...
6、NoSQL的四大分类
6、NoSQL的四大分类 kv键值对 不同公司不同的实现 新浪:Redis美团:RedisTair阿里、百度:Redismemcache 文档型数据库(bson格式和json一样) MongoDB MongoDB是一个基于分布式文件存储的数据库,一般用于存储…...
基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来…...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...
基于matlab策略迭代和值迭代法的动态规划
经典的基于策略迭代和值迭代法的动态规划matlab代码,实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解
在 C/C 编程的编译和链接过程中,附加包含目录、附加库目录和附加依赖项是三个至关重要的设置,它们相互配合,确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中,这些概念容易让人混淆,但深入理解它们的作用和联…...
Caliper 负载(Workload)详细解析
Caliper 负载(Workload)详细解析 负载(Workload)是 Caliper 性能测试的核心部分,它定义了测试期间要执行的具体合约调用行为和交易模式。下面我将全面深入地讲解负载的各个方面。 一、负载模块基本结构 一个典型的负载模块(如 workload.js)包含以下基本结构: use strict;/…...
LOOI机器人的技术实现解析:从手势识别到边缘检测
LOOI机器人作为一款创新的AI硬件产品,通过将智能手机转变为具有情感交互能力的桌面机器人,展示了前沿AI技术与传统硬件设计的完美结合。作为AI与玩具领域的专家,我将全面解析LOOI的技术实现架构,特别是其手势识别、物体识别和环境…...

FFmpeg avformat_open_input函数分析
函数内部的总体流程如下: avformat_open_input 精简后的代码如下: int avformat_open_input(AVFormatContext **ps, const char *filename,ff_const59 AVInputFormat *fmt, AVDictionary **options) {AVFormatContext *s *ps;int i, ret 0;AVDictio…...

Axure 下拉框联动
实现选省、选完省之后选对应省份下的市区...

Linux入门(十五)安装java安装tomcat安装dotnet安装mysql
安装java yum install java-17-openjdk-devel查找安装地址 update-alternatives --config java设置环境变量 vi /etc/profile #在文档后面追加 JAVA_HOME"通过查找安装地址命令显示的路径" #注意一定要加$PATH不然路径就只剩下新加的路径了,系统很多命…...