rust语言
概述
可以应用于系统级别,类型安全,无GC(garbage collection),没有额外的性能开销。使用所有权机制管理内存,具有一组在编译时候的规则。RUST代表未来的编程趋势。
hello world
常用命令:
cargo new
cargo new program --lib
cargo build
cargo run
cargo clean
C盘用户名下.cargo/config中可以换下载源
VScode插件:rust, rust-analyzer, Rust Test Lens
变量和数据类型
let声明变量,默认不可变,前置mut变为可变变量。
use std::io;
fn main() {
let mut x = String::new();
println!("hello");
match io::stdin().read_line(&mut x) {
Ok(_) => {
println!("I say: {}", x);
}
_ => {}
}
}
- Integer
分为有符号型和无符号型, i32, usize等 - Boolean
true,false - Character字符类型
单引号,let a = 'a'; let smile = '\u{1F601}' - &str 字符串类型
双引号,let cat: &str = "cat";
println!是宏,输出到终端;注释用//
let a = 5 // 默认是i32
let b = 1.2 // 默认是f64
let c = 'd' // 默认是char
let x = "ff" // 默认是&str
println!("{}", a);
控制流程
- 循环
loop,while,for
const MAX_NUM: i32 = 10;
fn main() {
print!("123");
let mut num = 0;
while num*num < MAX_NUM {
println!("while: {0} * {0} = {1}", num, num*num); // 0和1代表后面变量的位置
num += 1;
}
// let mut num = 0; // rust支持重新定义
num = 0; // 或者赋值都行
loop { // loop是无限循环,需要手动break
println!("loop: {0} * {0} = {1}", num, num*num); // 0和1代表后面变量的位置
num += 1;
if num*num > MAX_NUM {
break;
}
}
}
- match
match会在编译时检查错误,if-else只会在运行时报错。
fn main() {
let x = 5;
match x {
5 => println!("ok"),
_ => println!("no 5") // _表示其他所有情况
}
}
函数
->指向返回值类型,最后一行可以不写return和分号,也可以写。
fn add_func(a: i32, b: i32) -> i32 {
a+b
}
fn main() {
println!("Hello, world!");
let res = add_func(3, 8);
println!("{}", res);
}
Closure闭包写法,也就是lambda表达式
fn add_func(a: i32, b: i32) -> i32 {
a+b
}
fn main() {
println!("Hello, world!");
let res = add_func(3, 8);
println!("{}", res);
// lambda
let sum = |a: i32, b: i32| -> i32 {
a+b
};
let res = sum(3, 4);
println!("{}", res);
}
枚举
#[derive(Debug)]
enum Position {
Left,
Right
}
fn main() {
let pos = Position::Left;
let pos_right = Position::Right;
match pos {
Position::Left => println!("left"),
Position::Right => println!("right")
}
println!("{:#?}", pos);
}
结构体
rust中没有class。struct包含多段数据的类型,每一段数据被称为field属性,访问属性用"."
struct Rectangle {
width: i32,
height: i32
}
fn main() {
let r = Rectangle {width:3, height:4};
println!("{}", r.width);
println!("{}", r.height);
}
关联函数与实例方法
struct Rectangle {
width: i32,
height: i32
}
impl Rectangle {
// 关联函数,与实例无关,Rectangle::area调用
fn area(width: i32, height: i32) -> i32 {
width * height
}
// 实例方法,需要“实例.函数”调用
fn area2(&self) -> i32 {
self.width * self.height
}
}
fn main() {
let res = Rectangle::area(3, 2);
println!("{}", res);
let r = Rectangle {width:3, height:4};
println!("{}", r.width);
println!("{}", r.height);
let res2 = Rectangle::area2(&r); // 写法1
println!("{}", res2);
let res2 = r.area2(); // 写法2
println!("{}", res2);
}
构造函数与self
struct Person {
name: String,
age: i32
}
impl Person {
pub fn new(name: String, age: i32) -> Self {
Person {
name,
age
}
}
// &self是不可变的this指针
pub fn greet(&self) -> String {
format!("Hi {}", self.name)
}
// &mut self是可变的this指针
pub fn up_age(&mut self) -> String {
self.age += 1;
format!("Hi {}", self.age)
}
// self是调用后立刻销毁
fn drop_self(self) {
println!("drop")
}
}
fn main() {
let mut demo = Person::new("mike".to_string(), 90);
println!("{},{}", demo.name, demo.age);
println!("{}", demo.greet());
println!("{}", demo.up_age());
demo.drop_self(); // 执行后就会销毁demo
println!("{}", demo.age); // 这里就会报错不存在实例
}
元组
类似的,还有数组、切片,但是在rust中更常用Vector。
元组匿名存储数据,不可变。
常用于函数返回值,提取变量。
fn one_two_three() -> (i32, i32, i32) {
(1, 2, 3)
}
fn main() {
let numbers = one_two_three();
println!("{:?}", numbers);
let (x, y, z) = one_two_three();
println!("{},{},{}", x, y, z);
}
OwnerShip
规则:每个值都有唯一的变量,称为所有者,当所有者超出作用域时,值会被销毁。
包括move,borrowed,clone,copy,reference,lifetime。
stack和heap
stack存储已知的大小的数据,快,基础数据类型等。
heap存储未知大小的数据,慢,struct等。
- move
浅拷贝+失效
let a = "ff".to_string(); let b = a; //a失效
let v1 = vec![1, 2, 3];
let v2 = v1; // v1 被移动到 v2,v1 不再有效
// 下面这行代码会报错,因为 v1 已经不再有效
// println!("{:?}", v1);
- clone
深拷贝,开辟新的空间
引用
reference,通过&可以获得值的引用,未获得值的所有权,所以不会在作用域结束后被销毁,这种情况叫做借用borrowed。
考虑以下代码:
struct A {
a: i32
}
fn r(a: A) {
println!("{}", a.a);
}
fn main() {
let b = A{a: 4};
r(b);
println!("{}", b.a); // 这里会报错
}
因为r(b)将b作为参数,此时b已经失效,改法:可以将r加一个返回值,然后再赋值给b;或者r加引用:
struct A {
a: i32
}
fn r(a: &A) {
println!("{}", a.a);
}
fn main() {
let b = A{a: 4};
r(&b);
println!("{}", b.a);
}
在同一作用域下,对某一块数据:可以有多个不可变引用,只能有一个可变引用,不能同时有一个可变引用和一个不可变引用。
copy和clone
#[derive(Clone)]
struct Person {
name: String,
age: i32
}
fn main() {
let man = Person {
name: "mike".to_string(),
age: 90
};
let a = man.clone(); // 这里如果不加clone,那么man会失效,下一行就会报错
println!("{}", man.name);
}
接下来看copy
#[derive(Clone)]
struct Person {
name: String,
age: i32
}
fn main() {
let man = Person {
name: "mike".to_string(),
age: 90
};
let a = man.clone();
println!("{}", man.name);
}
生命周期
rust中所有引用都有自己的生命周期,表示引用有效的作用域,一般是隐式的,但不可推断时会报错,需要手动标注生命周期。
生命周期注解不是生命周期本身,而是用于描述不同引用之间生命周期的关系。
fn main() {
let string1 = String::from("hello");
let string2 = String::from("world");
let result = longest(string1.as_str(), string2.as_str());
println!("The longest string is {}", result);
}
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x
} else {
y
}
}
String
&str是不可变的String,长度确定,放在栈上,let cat = "cat";
String是object,放在heap上, let dog = String::from("dog");
fn main() {
let cat = "cat";
println!("{}", cat);
let dog = String::new();
println!("dog {}", dog);
let dog = String::from("sadwd");
println!("dog {}", dog);
let dog = "s".to_string();
println!("dog {}", dog);
let mut dog = format!("{}", "awewased");
println!("dog {}", dog);
println!("{}", dog.len());
dog.push('!');
dog.push_str("@@@@@");
println!("dog {}", dog);
}
cat
dog
dog sadwd
dog s
dog awewased
8
dog awewased!@@@@@
Vector
在rust中比较常用。
fn main() {
let mut arr: Vec<i32> = vec![1;5];
arr.push(2);
arr.remove(0);
println!("{:?}", arr);
// 提供一个防止越界的索引方法
match arr.get(100) {
Some(item) => println!("{}", item),
None => {}
}
// 遍历方法
for item in arr.iter() {
println!("{}", item);
}
}
特质
与接口和抽象类类似,给结构体添加定义的行为。
struct A {
name: String,
}
impl Person for A {
fn new(awesome: String) -> Self {
A {
name: awesome
}
}
fn language(&self) -> &str {
"A"
}
fn say_hello(&self) {
println!("Hiiiiii")
}
}
struct B {
name: String,
}
impl Person for B {
fn new(awesome: String) -> Self {
B {
name: awesome
}
}
fn language(&self) -> &str {
"B"
}
fn say_hello(&self) {
println!("Hiiiiii")
}
}
trait Person {
fn new(awesome: String) -> Self;
fn language(&self) -> &str;
fn say_hello(&self) {println!("Hello world!")}
}
fn main() {
let a = A::new("APerson".to_string());
let b = B::new("BPerson".to_string());
a.say_hello();
b.say_hello();
}
泛型
trait Bark {
fn bark(&self) -> String;
}
struct Dog {
species: String
}
impl Bark for Dog {
fn bark(&self) -> String {
format!("{} barking", self.species)
}
}
fn bark<T: Bark>(b: T) {
println!("{}", b.bark());
}
fn main() {
let dog = Dog{species: "yellow fur".to_string()};
bark(dog);
}
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现