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是一个基于分布式文件存储的数据库,一般用于存储…...

(动态规划) 剑指 Offer 60. n个骰子的点数 ——【Leetcode每日一题】
❓ 剑指 Offer 60. n个骰子的点数 难度:中等 把 n 个骰子扔在地上,所有骰子朝上一面的点数之和为 s 。输入 n,打印出s的所有可能的值出现的概率。 你需要用一个浮点数数组返回答案,其中第 i 个元素代表这 n 个骰子所能掷出的点…...

ArrayList与顺序表
文章目录 一. 顺序表是什么二. ArrayList是什么三. ArrayList的构造方法四. ArrayList的常见方法4.1 add()4.2 size()4.3 remove()4.4 get()4.5 set()4.6 contains()4.7 lastIndexOf()和 indexOf()4.8 subList()4.9 clear() 以上就是ArrayList的常见方法!…...

【【萌新的STM32-22中断概念的简单补充】】
萌新的STM32学习22-中断概念的简单补充 我们需要注意的是这句话 从上面可以看出,STM32F1 供给 IO 口使用的中断线只有 16 个,但是 STM32F1 的 IO 口却远远不止 16 个,所以 STM32 把 GPIO 管脚 GPIOx.0~GPIOx.15(xA,B,C,D,E,F,G)分别对应中断…...

Java 中数据结构HashMap的用法
Java HashMap HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。 HashMap 实现了 Map 接口,根据键的 HashCode 值存储数据,具有很快的访问速度,最多允许一条记录的键为 null,不支持线程同步。 HashMap 是…...

Request对象和response对象
一、概念 request对象和response对象是通过Servlet容器(如Tomcat)自动创建并传递给Servlet的。 Servlet容器负责接收客户端的请求,并将请求信息封装到request对象中,然后将request对象传 递给相应的Servlet进行处理。类似地&…...

设计模式之桥接模式
文章目录 一、介绍二、案例1. 组件抽象化2. 桥梁抽象化 一、介绍 桥接模式,属于结构型设计模式。通过提供抽象与实现之间的桥接结构,把抽象化与实现化解耦,使得二者可以独立变化。 《Head First 设计模式》: 将抽象和实现放在两…...

pom.xml配置文件失效,显示已忽略的pom.xml --- 解决方案
现象: 在 Maven 创建模块Moudle时,由于开始没有正确创建好,所以把它删掉了,然后接着又创建了与一个与之前被删除的Moudle同名的Moudle时,出现了 Ignore pom.xml,并且新创建的 Module 的 pom.xml配置文件失效…...

文本编辑器Vim常用操作和技巧
文章目录 1. Vim常用操作1.1 Vim简介1.2 Vim工作模式1.3 插入命令1.4 定位命令1.5 删除命令1.6 复制和剪切命令1.7 替换和取消命令1.8 搜索和搜索替换命令1.9 保存和退出命令 2. Vim使用技巧 1. Vim常用操作 1.1 Vim简介 Vim是一个功能强大的全屏幕文本编辑器,是L…...

【算法系列篇】位运算
文章目录 前言什么是位运算算法1.判断字符是否唯一1.1 题目要求1.2 做题思路1.3 Java代码实现 2. 丢失的数字2.1 题目要求2.2 做题思路2.3 Java代码实现 3. 两数之和3.1 题目要求3.2 做题思路3.3 Java代码实现 4. 只出现一次的数字4.1 题目要求4.2 做题思路4.3 Java代码实现 5.…...

机器学习的测试和验证(Machine Learning 研习之五)
关于 Machine Learning 研习之三、四,可到秋码记录上浏览。 测试和验证 了解模型对新案例的推广效果的唯一方法是在新案例上进行实际尝试。 一种方法是将模型投入生产并监控其性能。 这很有效,但如果你的模型非常糟糕,你的用户会抱怨——这…...