变量和可变性
Rust 中变量默认是不可变的(immutable),使用 mut 关键字可声明可变变量。
在 Rust 中,变量使用 let 关键字声明。默认情况下,变量一旦赋值就不能再修改,这有助于编写安全且易于推理的代码。
1. 不可变变量
1 2 3 4 5 6 fn main () { let x = 5 ; println! ("x 的值是: {}" , x); }
2. 可变变量
1 2 3 4 5 6 7 fn main () { let mut y = 10 ; println! ("初始值: {}" , y); y = 20 ; println! ("修改后: {}" , y); }
3. 常量
1 2 3 4 5 6 7 const MAX_POINTS: u32 = 100_000 ;fn main () { println! ("最大点数: {}" , MAX_POINTS); }
4. 变量遮蔽(Shadowing)
1 2 3 4 5 6 7 8 9 fn main () { let x = 5 ; let x = x + 1 ; println! ("x = {}" , x); let spaces = " " ; let spaces = spaces.len (); println! ("空格数: {}" , spaces); }
数据类型(标量与复合)
Rust 是静态类型语言,编译时必须知道所有变量的类型。标量类型表示单一值,复合类型表示一组值。
1. 标量类型(Scalar Types)
整数类型
长度
有符号
无符号
8 位
i8
u8
16 位
i16
u16
32 位
i32
u32
64 位
i64
u64
128 位
i128
u128
arch
isize
usize
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 fn main () { let a : i32 = -42 ; let b : u8 = 255 ; let c : usize = 100 ; let d = 1_000_000 ; let hex = 0xff ; let oct = 0o77 ; let bin = 0b1111_0000 ; let byte = b'A' ; println! ("a={}, b={}, c={}, d={}" , a, b, c, d); println! ("hex={}, oct={}, bin={}, byte={}" , hex, oct, bin, byte); }
浮点数类型
1 2 3 4 5 6 7 8 9 10 11 12 fn main () { let x : f32 = 3.14 ; let y : f64 = 2.71828 ; let z = 1.0 ; println! ("加: {}" , x + 1.0 ); println! ("减: {}" , y - 1.0 ); println! ("乘: {}" , 2.5 * 2.0 ); println! ("除: {}" , 5.0 / 2.0 ); println! ("取余: {}" , 7.0 % 3.0 ); }
布尔类型
1 2 3 4 5 6 7 8 9 10 11 fn main () { let t : bool = true ; let f : bool = false ; let is_ok = true ; if is_ok { println! ("一切正常!" ); } println! ("t={}, f={}" , t, f); }
字符类型
1 2 3 4 5 6 7 8 9 fn main () { let c : char = 'A' ; let emoji : char = '🦀' ; let zh : char = '中' ; println! ("c={}, emoji={}, zh={}" , c, emoji, zh); println! ("char 占用 {} 字节" , std::mem::size_of::<char >()); }
2. 复合类型(Compound Types)
元组(Tuple)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 fn main () { let tup : (i32 , f64 , char ) = (500 , 6.4 , 'R' ); let (x, y, z) = tup; println! ("x={}, y={}, z={}" , x, y, z); println! ("第一个: {}" , tup.0 ); println! ("第二个: {}" , tup.1 ); println! ("第三个: {}" , tup.2 ); let empty : () = (); }
数组(Array)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 fn main () { let arr : [i32 ; 5 ] = [1 , 2 , 3 , 4 , 5 ]; let zeros = [0 ; 3 ]; println! ("第一个: {}" , arr[0 ]); println! ("数组长度: {}" , arr.len ()); for element in arr.iter () { println! ("元素: {}" , element); } for (i, val) in arr.iter ().enumerate () { println! ("arr[{}] = {}" , i, val); } }
函数与作用域
Rust 使用 fn 关键字定义函数,函数名遵循蛇形命名法(snake_case)。main 函数是程序的入口点。
1. 函数定义与调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 fn main () { greet (); let result = add (10 , 20 ); println! ("10 + 20 = {}" , result); } fn greet () { println! ("Hello, Rust!" ); } fn add (a: i32 , b: i32 ) -> i32 { a + b }
2. 语句与表达式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 fn main () { let x = 5 ; let y = { let a = 3 ; a + 1 }; println! ("y = {}" , y); let z = double (5 ); println! ("double(5) = {}" , z); } fn double (n: i32 ) -> i32 { n * 2 }
3. 作用域
1 2 3 4 5 6 7 8 9 10 11 12 13 fn main () { let outer = 100 ; { let inner = 200 ; println! ("内部: outer={}, inner={}" , outer, inner); } println! ("外部: outer={}" , outer); }
流程控制
Rust 通过 if、loop、while、for 来控制代码的执行流程。
1. if 表达式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 fn main () { let number = 7 ; if number < 5 { println! ("数字小于 5" ); } else if number == 5 { println! ("数字等于 5" ); } else { println! ("数字大于 5" ); } let result = if number % 2 == 0 { "偶数" } else { "奇数" }; println! ("{} 是{}" , number, result); }
2. loop 循环
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 fn main () { let mut count = 0 ; loop { count += 1 ; println! ("count = {}" , count); if count >= 3 { break ; } } let result = loop { count += 1 ; if count == 10 { break count * 2 ; } }; println! ("result = {}" , result); }
3. while 循环
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 fn main () { let mut n = 3 ; while n > 0 { println! ("倒计时: {}" , n); n -= 1 ; } println! ("发射!🚀" ); let arr = [10 , 20 , 30 , 40 , 50 ]; let mut index = 0 ; while index < arr.len () { println! ("arr[{}] = {}" , index, arr[index]); index += 1 ; } }
4. for 循环
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 fn main () { let arr = [10 , 20 , 30 , 40 , 50 ]; for element in arr.iter () { println! ("元素: {}" , element); } for i in 0 ..5 { println! ("i = {}" , i); } for i in 1 ..=3 { println! ("i = {}" , i); } for i in (1 ..=5 ).rev () { println! ("倒序: {}" , i); } }
所有权与借用(Ownership and Borrowing)
所有权是 Rust 最独特的特性,它让 Rust 无需垃圾回收器就能保证内存安全。所有权规则:每个值有且只有一个所有者;值在所有者离开作用域时被释放。
1. 所有权规则
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 fn main () { let s1 = String ::from ("hello" ); println! ("s1 = {}" , s1); let s2 = s1; println! ("s2 = {}" , s2); { let s3 = String ::from ("temp" ); println! ("内部: {}" , s3); } }
2. 所有权与函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 fn main () { let s = String ::from ("hello" ); takes_ownership (s); let x = 5 ; makes_copy (x); println! ("x 仍然可用: {}" , x); let s1 = gives_ownership (); let s2 = String ::from ("world" ); let s3 = takes_and_gives_back (s2); println! ("s1={}, s3={}" , s1, s3); } fn takes_ownership (s: String ) { println! ("获取了所有权: {}" , s); } fn makes_copy (n: i32 ) { println! ("复制了: {}" , n); } fn gives_ownership () -> String { let s = String ::from ("from function" ); s } fn takes_and_gives_back (s: String ) -> String { s }
3. 借用(Borrowing)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 fn main () { let s = String ::from ("hello" ); let len = calculate_length (&s); println! ("'{}' 的长度是 {}" , s, len); let mut s2 = String ::from ("hello" ); change (&mut s2); println! ("修改后: {}" , s2); let r1 = &s2; let r2 = &s2; println! ("r1={}, r2={}" , r1, r2); let r3 = &mut s2; r3.push_str ("!!!" ); println! ("r3={}" , r3); } fn calculate_length (s: &String ) -> usize { s.len () } fn change (s: &mut String ) { s.push_str (", world!" ); }
引用与切片(References and Slices)
切片(Slice)是对集合中连续元素的引用,不拥有数据。最常见的切片类型是字符串切片 &str 和数组切片 &[T]。
1. 字符串切片
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 fn main () { let s = String ::from ("hello world" ); let hello = &s[0 ..5 ]; let world = &s[6 ..11 ]; println! ("{}, {}!" , hello, world); let h = &s[..5 ]; let w = &s[6 ..]; let all = &s[..]; println! ("h={}, w={}, all={}" , h, w, all); let first = first_word (&s); println! ("第一个单词: {}" , first); let literal = "hello world" ; let first2 = first_word (literal); println! ("第一个单词: {}" , first2); } fn first_word (s: &str ) -> &str { let bytes = s.as_bytes (); for (i, &item) in bytes.iter ().enumerate () { if item == b' ' { return &s[..i]; } } &s[..] }
2. 数组切片
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 fn main () { let arr = [1 , 2 , 3 , 4 , 5 ]; let slice : &[i32 ] = &arr[1 ..4 ]; println! ("切片: {:?}" , slice); println! ("第一个元素: {}" , slice[0 ]); println! ("切片长度: {}" , slice.len ()); let empty : &[i32 ] = &[]; println! ("empty.is_empty() = {}" , empty.is_empty ()); for val in slice.iter () { println! ("元素: {}" , val); } }
结构体(Struct)和方法
结构体是一种自定义数据类型,用于将多个相关的值组合成一个有意义的整体。可以为其定义方法,方法定义在 impl 块中。
1. 定义与实例化结构体
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 struct User { username: String , email: String , active: bool , } fn main () { let user1 = User { email: String ::from ("alice@example.com" ), username: String ::from ("alice" ), active: true , }; println! ("用户名: {}, 邮箱: {}" , user1.username, user1.email); let mut user2 = User { email: String ::from ("bob@example.com" ), username: String ::from ("bob" ), active: false , }; user2.active = true ; println! ("{} 激活状态: {}" , user2.username, user2.active); let user3 = User { email: String ::from ("charlie@example.com" ), ..user2 }; println! ("新用户: {}, {}" , user3.username, user3.email); }
2. 元组结构体和单元结构体
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 struct Color (i32 , i32 , i32 );struct Point (f64 , f64 );struct AlwaysEqual ;fn main () { let black = Color (0 , 0 , 0 ); let origin = Point (0.0 , 0.0 ); println! ("R: {}, G: {}, B: {}" , black.0 , black.1 , black.2 ); println! ("x: {}, y: {}" , origin.0 , origin.1 ); let _subject = AlwaysEqual; }
3. 方法定义(impl 块)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 struct Rectangle { width: u32 , height: u32 , } impl Rectangle { fn square (size: u32 ) -> Rectangle { Rectangle { width: size, height: size, } } fn area (&self ) -> u32 { self .width * self .height } fn double_size (&mut self ) { self .width *= 2 ; self .height *= 2 ; } fn destroy (self ) -> (u32 , u32 ) { (self .width, self .height) } fn can_hold (&self , other: &Rectangle) -> bool { self .width > other.width && self .height > other.height } } fn main () { let mut rect = Rectangle { width: 30 , height: 50 , }; println! ("面积: {} 平方像素" , rect.area ()); rect.double_size (); println! ("放大后: {} x {}" , rect.width, rect.height); let sq = Rectangle::square (10 ); println! ("正方形面积: {}" , sq.area ()); let small = Rectangle { width: 5 , height: 5 }; println! ("rect 能容纳 small 吗?{}" , rect.can_hold (&small)); }
枚举与模式匹配
枚举(enum)定义了一组可能的取值类型。结合 match 模式匹配,Rust 能安全地处理所有情况,编译器会检查是否覆盖了所有分支。
1. 枚举定义与使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 #[derive(Debug)] enum IpAddrKind { V4, V6, } #[derive(Debug)] enum IpAddr { V4 (u8 , u8 , u8 , u8 ), V6 (String ), } impl IpAddr { fn describe (&self ) -> String { match self { IpAddr::V4 (a, b, c, d) => format! ("IPv4: {}.{}.{}.{}" , a, b, c, d), IpAddr::V6 (addr) => format! ("IPv6: {}" , addr), } } } fn main () { let four = IpAddrKind::V4; let six = IpAddrKind::V6; println! ("{:?}, {:?}" , four, six); let home = IpAddr::V4 (127 , 0 , 0 , 1 ); let loopback = IpAddr::V6 (String ::from ("::1" )); println! ("{:?}" , home); println! ("{}" , home.describe ()); println! ("{}" , loopback.describe ()); }
2. Option 枚举(替代空值)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 fn main () { let some_number = Some (5 ); let some_string = Some ("hello" ); let absent : Option <i32 > = None ; let x = 5 ; let y = Some (10 ); let sum = x + y.unwrap_or (0 ); println! ("sum = {}" , sum); }
3. match 模式匹配
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 #[derive(Debug)] enum Coin { Penny, Nickel, Dime, Quarter, } #[derive(Debug)] enum Message { Quit, Move { x: i32 , y: i32 }, Write (String ), ChangeColor (i32 , i32 , i32 ), } fn main () { let coin = Coin::Dime; let value = value_in_cents (coin); println! ("价值: {} 美分" , value); let opt_val = Some (3 ); let result = plus_one (opt_val); println! ("{:?}" , result); let none_val = plus_one (None ); println! ("{:?}" , none_val); let msg = Message::Write (String ::from ("hello" )); process_message (msg); let msg2 = Message::Move { x: 10 , y: 20 }; process_message (msg2); } fn value_in_cents (coin: Coin) -> u8 { match coin { Coin::Penny => { println! ("幸运便士!" ); 1 } Coin::Nickel => 5 , Coin::Dime => 10 , Coin::Quarter => 25 , } } fn plus_one (x: Option <i32 >) -> Option <i32 > { match x { None => None , Some (i) => Some (i + 1 ), } } fn process_message (msg: Message) { match msg { Message::Quit => println! ("退出" ), Message::Move { x, y } => println! ("移动到 ({}, {})" , x, y), Message::Write (text) => println! ("写入: {}" , text), Message::ChangeColor (r, g, b) => println! ("改为颜色 ({}, {}, {})" , r, g, b), } }
4. if let 简洁控制流
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 fn main () { let config_max = Some (3u8 ); match config_max { Some (max) => println! ("最大值配置为 {}" , max), _ => (), } if let Some (max) = config_max { println! ("最大值配置为 {}" , max); } let coin = Some (5 ); if let Some (value) = coin { println! ("硬币价值: {}" , value); } else { println! ("没有硬币" ); } }
常见集合类型及常用操作
Rust 标准库提供了几种通用的集合类型:Vec<T>(动态数组)、String(字符串)、HashMap<K,V>(哈希映射)。
1. Vec<T> 动态数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 fn main () { let mut v1 : Vec <i32 > = Vec ::new (); let mut v2 = vec! [1 , 2 , 3 ]; v1.push (10 ); v1.push (20 ); v1.push (30 ); println! ("v1[0] = {}" , v1[0 ]); println! ("v1.get(1) = {:?}" , v1.get (1 )); println! ("v1.get(100) = {:?}" , v1.get (100 )); for val in &v2 { println! ("元素: {}" , val); } for val in &mut v2 { *val *= 2 ; } println! ("翻倍后: {:?}" , v2); println! ("长度: {}" , v2.len ()); println! ("是否为空: {}" , v2.is_empty ()); v2.pop (); println! ("pop 后: {:?}" , v2); #[derive(Debug)] enum Cell { Int (i32 ), Text (String ), Float (f64 ), } let row = vec! [ Cell::Int (42 ), Cell::Text (String ::from ("hello" )), Cell::Float (3.14 ), ]; println! ("行数据: {:?}" , row); }
2. String 字符串
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 fn main () { let mut s1 = String ::new (); let mut s2 = String ::from ("hello" ); let s3 = "world" .to_string (); s1.push_str ("rust" ); s2.push (' ' ); s2.push_str ("world" ); let joined = format! ("{}-{}-{}" , s1, s2, s3); println! ("拼接结果: {}" , joined); let combined = s1 + " & " + &s3; println! ("combined: {}" , combined); for c in "你好" .chars () { println! ("字符: {}" , c); } for b in "ABC" .bytes () { println! ("字节: {}" , b); } let hello = String ::from ("你好世界" ); let slice = &hello[0 ..3 ]; println! ("切片: {}" , slice); let s = String ::from ("hello world" ); println! ("长度(字节): {}" , s.len ()); println! ("是否为空: {}" , s.is_empty ()); println! ("包含'world': {}" , s.contains ("world" )); println! ("替换: {}" , s.replace ("world" , "rust" )); let words : Vec <&str > = s.split (' ' ).collect (); println! ("拆分结果: {:?}" , words); println! ("转大写: {}" , s.to_uppercase ()); println! ("去除空白: {}" , " abc " .trim ()); }
3. HashMap<K, V> 哈希映射
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 use std::collections::HashMap;fn main () { let mut scores = HashMap::new (); scores.insert (String ::from ("Blue" ), 10 ); scores.insert (String ::from ("Yellow" ), 50 ); let team = String ::from ("Blue" ); match scores.get (&team) { Some (score) => println! ("Blue 队分数: {}" , score), None => println! ("Blue 队不存在" ), } for (key, value) in &scores { println! ("{}: {}" , key, value); } scores.entry (String ::from ("Blue" )).or_insert (100 ); scores.entry (String ::from ("Red" )).or_insert (30 ); println! ("插入后: {:?}" , scores); let text = "hello world hello" ; let mut word_count = HashMap::new (); for word in text.split_whitespace () { let count = word_count.entry (word).or_insert (0 ); *count += 1 ; } println! ("词频统计: {:?}" , word_count); let teams = vec! [String ::from ("Blue" ), String ::from ("Yellow" )]; let initial_scores = vec! [10 , 50 ]; let team_scores : HashMap<_, _> = teams.into_iter ().zip (initial_scores.into_iter ()).collect (); println! ("聚合结果: {:?}" , team_scores); }
模块系统和包管理
Rust 的模块系统由四个核心概念组成:包(Package)、Crate(库/二进制)、模块(Module)、路径(Path)。use 关键字用于将路径引入作用域。
1. 模块定义与可见性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 mod front_of_house { pub mod hosting { pub fn add_to_waitlist () { println! ("已添加到等候名单" ); } fn seat_at_table () { println! ("请就座" ); } } mod serving { fn take_order () { println! ("点菜" ); super::hosting::add_to_waitlist (); } } } pub use front_of_house::hosting;use front_of_house::hosting::add_to_waitlist;fn eat_at_restaurant () { crate::front_of_house::hosting::add_to_waitlist (); front_of_house::hosting::add_to_waitlist (); add_to_waitlist (); } fn main () { eat_at_restaurant (); }
2. 多文件模块结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 mod utils { pub fn greet (name: &str ) { println! ("你好,{}!" , name); } } fn main () { utils::greet ("Rustacean" ); }
3. use 关键字用法
1 2 3 4 5 6 7 8 9 10 11 12 13 use std::collections::HashMap;use std::io::{self , Write}; use std::collections::*; fn main () { let mut map = HashMap::new (); map.insert ("key" , "value" ); println! ("{:?}" , map); let mut stdout = io::stdout (); writeln! (stdout, "通过 use 简化了路径!" ).unwrap (); }
4. Cargo 包管理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 fn main () { println! ("Cargo 是 Rust 的构建系统和包管理器!" ); }
错误处理
Rust 将错误分为两类:可恢复错误(Result<T, E>)和不可恢复错误(panic!)。推荐使用 Result 进行错误传播。
1. panic! 宏(不可恢复错误)
1 2 3 4 5 6 7 8 9 10 11 12 fn main () { let v = vec! [1 , 2 , 3 ]; println! ("v 有效: {:?}" , v); }
2. Result<T, E>(可恢复错误)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 use std::fs::File;use std::io::{self , Read, ErrorKind};fn main () { let file_result = File::open ("hello.txt" ); let file = match file_result { Ok (f) => f, Err (error) => match error.kind () { ErrorKind::NotFound => match File::create ("hello.txt" ) { Ok (fc) => fc, Err (e) => panic! ("无法创建文件: {:?}" , e), }, other_error => panic! ("打开文件出错: {:?}" , other_error), }, }; println! ("文件打开成功: {:?}" , file.metadata ()); let _file2 = File::open ("hello.txt" ).unwrap_or_else (|error| { if error.kind () == ErrorKind::NotFound { File::create ("hello.txt" ).unwrap_or_else (|error| { panic! ("无法创建文件: {:?}" , error); }) } else { panic! ("打开文件出错: {:?}" , error); } }); } fn demo_unwrap () { let _f = File::open ("hello.txt" ).unwrap (); let _f = File::open ("hello.txt" ).expect ("无法打开 hello.txt" ); }
3. 错误传播(? 操作符)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 use std::fs::{self , File};use std::io::{self , Read};fn read_username_from_file_v1 () -> Result <String , io::Error> { let f = File::open ("username.txt" ); let mut f = match f { Ok (file) => file, Err (e) => return Err (e), }; let mut s = String ::new (); match f.read_to_string (&mut s) { Ok (_) => Ok (s), Err (e) => Err (e), } } fn read_username_from_file_v2 () -> Result <String , io::Error> { let mut f = File::open ("username.txt" )?; let mut s = String ::new (); f.read_to_string (&mut s)?; Ok (s) } fn read_username_from_file_v3 () -> Result <String , io::Error> { let mut s = String ::new (); File::open ("username.txt" )?.read_to_string (&mut s)?; Ok (s) } fn read_username_from_file_v4 () -> Result <String , io::Error> { fs::read_to_string ("username.txt" ) } fn main () -> Result <(), Box <dyn std::error::Error>> { match read_username_from_file_v4 () { Ok (name) => println! ("用户名: {}" , name), Err (e) => eprintln! ("读取错误: {}" , e), } Ok (()) }
泛型(Generics)
泛型允许编写适用于多种类型的代码,减少重复。Rust 的泛型在编译时通过单态化(monomorphization)实现零成本抽象——为每个使用的具体类型生成专用代码。
1. 函数中的泛型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 fn largest_i32 (list: &[i32 ]) -> &i32 { let mut largest = &list[0 ]; for item in list { if item > largest { largest = item; } } largest } fn largest <T: PartialOrd >(list: &[T]) -> &T { let mut largest = &list[0 ]; for item in list { if item > largest { largest = item; } } largest } fn main () { let numbers = vec! [34 , 50 , 25 , 100 , 65 ]; println! ("最大数: {}" , largest (&numbers)); let chars = vec! ['y' , 'm' , 'a' , 'q' ]; println! ("最大字符: {}" , largest (&chars)); }
2. 结构体中的泛型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 #[derive(Debug)] struct Point <T> { x: T, y: T, } #[derive(Debug)] struct Point2 <T, U> { x: T, y: U, } impl <T> Point<T> { fn x (&self ) -> &T { &self .x } } impl Point <f64 > { fn distance_from_origin (&self ) -> f64 { (self .x.powi (2 ) + self .y.powi (2 )).sqrt () } } impl <T: Clone , U> Point2<T, U> { fn mixup <V, W>(self , other: Point2<V, W>) -> Point2<T, W> { Point2 { x: self .x.clone (), y: other.y, } } } fn main () { let integer_point = Point { x: 5 , y: 10 }; let float_point = Point { x: 1.0 , y: 4.0 }; println! ("int_point.x = {}" , integer_point.x ()); println! ("float_point 到原点距离 = {}" , float_point.distance_from_origin ()); let p1 = Point2 { x: 5 , y: "hello" }; let p2 = Point2 { x: "world" , y: 'R' }; let p3 = p1.mixup (p2); println! ("mixup: {:?}" , p3); let _flexible = Point2 { x: 5 , y: 4.0 }; }
3. 枚举中的泛型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #[derive(Debug)] enum MyResult <T, E> { Success (T), Failure (E), } fn main () { let ok : MyResult<i32 , String > = MyResult::Success (42 ); let err : MyResult<i32 , String > = MyResult::Failure (String ::from ("出错了" )); println! ("{:?}, {:?}" , ok, err); let x : Option <i32 > = Some (10 ); let y : Result <i32 , &str > = Ok (20 ); println! ("{:?}, {:?}" , x, y); }
Trait 与 Trait Bound
Trait 定义了类型之间共享的行为,类似于其他语言中的接口(interface)。Trait Bound 用于约束泛型参数必须实现某些 trait。
1. 定义和实现 Trait
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 pub trait Summary { fn summarize_author (&self ) -> String ; fn summarize (&self ) -> String { format! ("(阅读更多来自 {} 的内容...)" , self .summarize_author ()) } } pub struct Article { pub headline: String , pub author: String , pub content: String , } pub struct Tweet { pub username: String , pub content: String , pub retweet: bool , } impl Summary for Article { fn summarize_author (&self ) -> String { format! ("@{}" , self .author) } } impl Summary for Tweet { fn summarize_author (&self ) -> String { format! ("@{}" , self .username) } fn summarize (&self ) -> String { format! ("{}: {}" , self .username, self .content) } } fn main () { let article = Article { headline: String ::from ("Rust 很强大" ), author: String ::from ("Ferris" ), content: String ::from ("今天我们来学习 Rust..." ), }; let tweet = Tweet { username: String ::from ("ferris_rustacean" ), content: String ::from ("Rust is awesome!" ), retweet: false , }; println! ("文章摘要: {}" , article.summarize ()); println! ("推文摘要: {}" , tweet.summarize ()); }
2. Trait Bound(约束)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 use std::fmt::{Debug , Display};pub fn notify (item: &impl Summary ) { println! ("快讯!{}" , item.summarize ()); } pub fn notify_bound <T: Summary>(item: &T) { println! ("快讯!{}" , item.summarize ()); } pub fn notify_and_debug (item: &(impl Summary + Display)) {}pub fn some_function <T, U>(t: &T, u: &U) -> String where T: Display + Clone , U: Clone + Debug , { format! ("t={}, u={:?}" , t, u) } pub fn returns_summarizable () -> impl Summary { Tweet { username: String ::from ("ferris" ), content: String ::from ("返回 impl Trait" ), retweet: false , } } fn main () { let tweet = returns_summarizable (); println! ("{}" , tweet.summarize ()); let s1 = String ::from ("hello" ); let s2 = String ::from ("world" ); println! ("{}" , some_function (&s1, &s2)); }
3. 派生 Trait(Derive)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 #[derive(Debug, Clone, PartialEq, Eq, Hash)] struct Person { name: String , age: u32 , } fn main () { let p1 = Person { name: String ::from ("Alice" ), age: 30 }; let p2 = p1.clone (); println! ("{:?}" , p1); println! ("p1 == p2: {}" , p1 == p2); }
4. Orphan Rule(孤儿规则)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 use std::fmt::Display;struct MyVec (Vec <i32 >);impl Display for MyVec { fn fmt (&self , f: &mut std::fmt::Formatter<'_ >) -> std::fmt::Result { write! (f, "MyVec with {} elements" , self .0 .len ()) } } fn main () { let mv = MyVec (vec! [1 , 2 , 3 ]); println! ("{}" , mv); }
生命周期(Lifetimes)
生命周期是 Rust 用来防止悬垂引用的机制。生命周期注解描述了引用之间存活时间的关系,大多数情况下编译器可自动推断,复杂场景需要手动标注。
1. 生命周期基础
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 fn main () { { let x = 5 ; let r = &x; println! ("r: {}" , r); } }
2. 函数签名中的生命周期注解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 fn longest <'a >(x: &'a str , y: &'a str ) -> &'a str { if x.len () > y.len () { x } else { y } } fn main () { let string1 = String ::from ("long string is long" ); { let string2 = String ::from ("xyz" ); let result = longest (&string1, &string2); println! ("最长的字符串是: {}" , result); } }
3. 结构体中的生命周期
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 #[derive(Debug)] struct Excerpt <'a > { part: &'a str , } impl <'a > Excerpt<'a > { fn level (&self ) -> i32 { 3 } fn announce_and_return_part (&self , announcement: &str ) -> &str { println! ("注意: {}" , announcement); self .part } } fn main () { let novel = String ::from ("从前有座山,山里有座庙..." ); let first_sentence = novel.split ('。' ).next ().expect ("找不到句号" ); let excerpt = Excerpt { part: first_sentence }; println! ("摘录: {:?}" , excerpt); println! ("返回: {}" , excerpt.announce_and_return_part ("请注意" )); }
4. 生命周期省略规则
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 fn first_word (s: &str ) -> &str { let bytes = s.as_bytes (); for (i, &item) in bytes.iter ().enumerate () { if item == b' ' { return &s[..i]; } } &s[..] } fn main () { let s = "hello world" ; println! ("第一个单词: {}" , first_word (s)); }
5. 静态生命周期
1 2 3 4 5 6 7 8 9 10 11 12 13 fn main () { let s : &'static str = "我是静态字符串,永远有效" ; println! ("{}" , s); let pi : &'static f64 = &3.14159 ; println! ("pi 近似值: {}" , pi); }
常用标准库函数与实用宏
Rust 标准库和内置宏提供了丰富的工具函数,掌握它们能大幅提升开发效率。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 fn main () { let name = "Ferris" ; let age = 5 ; println! ("你好,{}!" , name); println! ("{0} 今年 {1} 岁,{0} 喜欢 Rust!" , name, age); println! ("{name} 写了 {count} 行代码" , name = "Alice" , count = 1000 ); let arr = vec! [1 , 2 , 3 ]; println! ("数组: {:?}" , arr); println! ("美化: {:#?}" , arr); let num = 255 ; println! ("十进制: {}, 十六进制: {:x}, 八进制: {:o}, 二进制: {:b}" , num, num, num, num); println! ("前导零: {:08}" , 42 ); println! ("精度: {:.3}" , 3.14159 ); print! ("不换行..." ); eprintln! ("这是错误输出!" ); let msg = format! ("{} + {} = {}" , 1 , 2 , 3 ); println! ("{}" , msg); }
2. 常用宏
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 fn main () { let v = vec! [1 , 2 , 3 , 4 , 5 ]; println! ("{:?}" , v); assert! (1 + 1 == 2 , "数学失效了!" ); assert_eq! (2 + 2 , 4 ); assert_ne! (2 + 2 , 5 ); let x = dbg!(5 * 10 ); let opt = Some (42 ); if matches!(opt, Some (x) if x > 0 ) { println! ("大于零的值!" ); } const GREETING: &str = concat! ("Hello" , ", " , "World!" ); println! ("{}" , GREETING); println! ("所有宏演示完成!" ); }
3. 常用标准库函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 use std::cmp;fn main () { let s = "hello world" ; println! ("是否包含: {}" , s.contains ("world" )); println! ("是否以...开头: {}" , s.starts_with ("he" )); println! ("是否以...结尾: {}" , s.ends_with ("ld" )); println! ("替换: {}" , s.replace ("world" , "Rust" )); println! ("查找位置: {:?}" , s.find ("o" )); let parts : Vec <&str > = s.split_whitespace ().collect (); println! ("按空白分割: {:?}" , parts); println! ("绝对值: {}" , (-5i32 ).abs ()); println! ("次方: {}" , 2i32 .pow (10 )); println! ("最大值: {}" , cmp::max (10 , 20 )); println! ("最小值: {}" , cmp::min (10 , 20 )); println! ("范围限制: {}" , 100i32 .clamp (0 , 50 )); println! ("是否为 2 的幂: {}" , 64u32 .is_power_of_two ()); let f = 3.14159_f64 ; println! ("四舍五入: {}" , f.round ()); println! ("向上取整: {}" , f.ceil ()); println! ("向下取整: {}" , f.floor ()); println! ("截断: {}" , f.trunc ()); println! ("平方根: {}" , f.sqrt ()); let opt_val = Some (3 ); println! ("unwrap_or: {}" , opt_val.unwrap_or (0 )); println! ("map: {:?}" , opt_val.map (|x| x * 2 )); println! ("and_then: {:?}" , opt_val.and_then (|x| Some (x + 1 ))); let filtered = opt_val.filter (|&x| x > 5 ); println! ("filter: {:?}" , filtered); let result : Result <i32 , &str > = Ok (42 ); println! ("Result unwrap_or: {}" , result.unwrap_or (0 )); println! ("Result map: {:?}" , result.map (|x| x * 2 )); let numbers = vec! [1 , 2 , 3 , 4 , 5 ]; let sum : i32 = numbers.iter ().sum (); let doubled : Vec <i32 > = numbers.iter ().map (|x| x * 2 ).collect (); let evens : Vec <&i32 > = numbers.iter ().filter (|&&x| x % 2 == 0 ).collect (); let found = numbers.iter ().find (|&&x| x > 3 ); println! ("sum: {}, doubled: {:?}, evens: {:?}, found: {:?}" , sum, doubled, evens, found); let num_str = "42" .parse::<i32 >().unwrap (); println! ("解析后的数字: {}" , num_str); let num_to_str = 42 .to_string (); println! ("转换的字符串: {}" , num_to_str); let small : u8 = 10 ; let big : u32 = small as u32 ; println! ("small as u32: {}" , big); }
4. 文件读写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 use std::fs;use std::io::{self , Write, BufRead, BufReader};use std::path::Path;fn main () -> io::Result <()> { fs::write ("output.txt" , "Hello, Rust!\n第二行内容" )?; let mut file = fs::OpenOptions::new () .append (true ) .open ("output.txt" )?; writeln! (file, "追加的一行" )?; let content = fs::read_to_string ("output.txt" )?; println! ("文件内容:\n{}" , content); let file = fs::File::open ("output.txt" )?; let reader = BufReader::new (file); for (i, line) in reader.lines ().enumerate () { println! ("第 {} 行: {}" , i + 1 , line?); } let path = Path::new ("output.txt" ); println! ("文件存在: {}" , path.exists ()); println! ("是文件: {}" , path.is_file ()); if Path::new ("." ).is_dir () { for entry in fs::read_dir ("." )? { let entry = entry?; println! ("目录项: {:?}" , entry.path ()); } } Ok (()) }
Rust 中的异步编程(async/await)
Rust 的异步编程基于 Future trait 和 async/await 语法。异步代码不会阻塞线程,而是让出控制权等待 I/O 完成。运行时(如 tokio)负责调度执行。
1. 异步基础概念
2. 基本 async/await 使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 async fn say_hello () -> String { String ::from ("Hello from async!" ) } async fn fetch_data (id: u32 ) -> String { format! ("数据-{}" , id) } async fn sequential () { let a = fetch_data (1 ).await ; let b = fetch_data (2 ).await ; println! ("顺序: a={}, b={}" , a, b); } async fn concurrent () { let (a, b) = tokio::join!( fetch_data (1 ), fetch_data (2 ), ); println! ("并发: a={}, b={}" , a, b); } fn main () { println! ("=== Rust 异步编程概念 ===" ); println! ("" ); println! ("核心概念:" ); println! ("1. async fn 返回一个 Future" ); println! ("2. .await 等待 Future 完成,线程不会被阻塞" ); println! ("3. tokio::spawn 可在后台并发执行任务" ); println! ("4. tokio::join! 同时等待多个 Future" ); println! ("5. tokio::select! 竞速等待,哪个先完成处理哪个" ); println! ("" ); println! ("实际使用时需添加依赖到 Cargo.toml:" ); println! (" tokio = {{ version = \"1\", features = [\"full\"] }}" ); }
3. 并发任务处理模式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 fn main () { println! ("异步并发常用模式:" ); println! ("- tokio::spawn: 后台并发执行任务,返回 JoinHandle" ); println! ("- tokio::join!: 同时等待多个 Future 完成" ); println! ("- tokio::select!: 竞速等待,处理最先完成的" ); println! ("- tokio::sync::mpsc: 异步多生产者单消费者通道" ); println! ("- tokio::sync::Mutex: 异步互斥锁" ); println! ("- Stream: 异步迭代器(需 futures 或 tokio-stream crate)" ); }
4. 异步编程完整示例
// 一个完整的异步 HTTP 请求示例(概念演示)
// 实际运行需要添加 reqwest 和 tokio 依赖
// Cargo.toml:
// [dependencies]
// tokio = { version = "1", features = ["full"] }
// reqwest = { version = "0.12", features = ["json"] }
// serde = { version = "1", features = ["derive"] }
// use serde::Deserialize;
//
// #[derive(Debug, Deserialize)]
// struct Post {
// #[serde(rename = "userId")]
// user_id: u32,
// id: u32,
// title: String,
// body: String,
// }
//
// async fn fetch_post(client: &reqwest::Client, id: u32) -> Result<Post, reqwest::Error> {
// let url = format!("https://jsonplaceholder.typicode.com/posts/{}", id);
// let post = client.get(&url).send().await?.json::<Post>().await?;
// Ok(post)
// }
//
// #[tokio::main]
// async fn main() -> Result<(), Box<dyn std::error::Error>> {
// let client = reqwest::Client::new();
//
// // 并发获取多个 post
// let (post1, post2, post3) = tokio::join!(
// fetch_post(&client, 1),
// fetch_post(&client, 2),
// fetch_post(&client, 3),
// );
//
// println!("Post 1: {:?}", post1?);
// println!("Post 2: {:?}", post2?);
// println!("Post 3: {:?}", post3?);
//
// Ok(())
// }
fn main() {
println!("完整异步示例结构如上。");
println!("");
println!("总结——异步编程最佳实践:");
println!("1. 选择合适的运行时(tokio 最流行)");
println!("2. 使用 join! 并发,而不是顺序 await");
println!("3. spawn 用于"发射后不管"的独立任务");
println!("4. select! 用于超时控制和竞速");
println!("5. 异步函数应该是非阻塞的(避免 CPU 密集型操作)");
println!("6. 用 spawn_blocking 处理同步 CPU 密集型代码");
println!("7. 使用 async Mutex/RwLock 而非 std 的同步版本");
}
**RUST Study Note 系列文章**
{% series 9 %}