Open WJ-Yuan opened 1 year ago
/**
* 变量
* 类型有 整型(8, 16, 32, 64, 128, size)、浮点型(8, 16, 32, 64, 128, size)、布尔型(true/false)、字符型(char)
*/
fn main() {
// 默认整型是 i32,浮点是 f64
let a: i32 = 5;
let b: f64 = 1.2;
let bb: bool = true;
let c: char = 'd';
let smile: char = '\u{1F601}';
let str_item: &str = "一个字符串";
println!("{}, {}, {}, {c}, {smile}, {str_item}", a, b, bb);
}
/**
* 控制流 - 条件
* if...else
*/
/**
* 控制流 - 循环
* loop 或 iteration
*
* 关键字
* - loop 无尽的循环
* - while 有条件的循环
* - for
*
* 可以通过 break 退出循环
* 通过 continue 退出当前循环
*/
const MAX: i32 = 10;
fn main() {
println!("Hello, World!");
let mut num: i32 = 0;
while num * num < 10 {
if num == 2 {
num += 1;
continue;
}
println!("while: {0} * {0} = {1}", num, num * num);
num += 1;
}
let mut num: i32 = 0;
loop {
println!("while: {0} * {0} = {1}", num, num * num);
num += 1;
if num * num > MAX {
break;
}
}
}
/**
* match
*
* 在流程控制这块,和 if...else 类似,但是必须写出所有条件下的执行代码
*
* match vs if...else
*
* - match 会在编译时检查错误
* - if...else 则不会,只会在运行时报错
*/
use rand::Rng;
fn main() {
let mut rng = rand::thread_rng();
let num = rng.gen_range(0..10);
if num > 5 {
println!("{num} > 5");
} else if num == 5 {
println!("{num} == 5");
} else {
println!("{num} < 5");
}
match num {
2 => println!("ok"),
5..=9 => println!("unknown"),
_ => println!("{num}"),
}
}
/**
* 函数
* 最后一行不加 ";",自动作为值返回
*/
// 普通函数
fn add_fun(a: i32, b:i32) -> i32 {
println!("a: {a}");
println!("b: {b}");
a + b
}
fn main() {
let res = add_fun(8, 9);
println!("{res}");
}
/**
* 闭包
* 又叫函数中的函数,匿名函数
* 也就是 lambda 表达式
*/
fn main() {
let sum = |a: i32, b: i32| -> i32{a + b};
let res = sum(3, 4);
println!("{res}");
}
/**
* 枚举 Enum
*
* 提高代码可读性;
* 提供标识给编译器(提高性能)
*
* 系统内置
* Result
* Option
*/
#[derive(Debug)] // 便于用 print 打印
enum Position {
Left,
Right
}
fn return_right(enum_item: Position) -> Position {
println!("{:?}", enum_item);
Position::Right
}
fn main () {
let pos = Position::Left;
match pos {
Position::Left => println!("left"),
Position::Right => println!("right"),
}
println!("{:?}", pos);
let right: Position = return_right(pos);
println!("{:?}", right);
}
/**
* 结构体 struct
* rust 中没有 class
*
* 属性
* struct 包含多段数据的类型
* 每一段数据被称为 field 属性
* 访问属性用 . 操作符
*
*
* struct 方法
*
* 类型:
* - 关联函数
* - 实例方法
*
*
* 构造函数及 self
*/
#[derive(Debug)] // 如果要 println 打印复合类型需要加这个
struct Rectangle {
width: i32,
height: i32
}
fn new(width: i32, height: i32) -> Rectangle {
Rectangle {
width,
height
}
}
impl Rectangle {
// 构造函数
fn new(width: i32, height: i32) -> Self {
Rectangle {
width,
height
}
}
fn area(width: i32, height: i32) -> i32 {
width * height
}
fn self_area(&self) -> i32 {
self.width * self.height
}
}
fn main() {
let rect = Rectangle::new(3, 4);
println!("{}, {}", rect.width, rect.height);
println!("{:?}", rect);
println!("{:#?}", rect); // 打印格式化
let area = Rectangle::area(rect.width, rect.height);
println!("{}", area);
let area_self = Rectangle::self_area(&rect);
println!("{}", area_self);
let rect_2 = new(3, 4);
println!("{:#?}", rect_2)
}
/**
* self
*
* &self
* &mut self
* self
* mut self - 用得很少
*/
#[derive(Debug)]
struct Person {
name: String,
age: i32,
}
impl Person {
pub fn new(name: String, age: i32) -> Self{ Person { name, age } }
// 类似 this 指针,但是是不可变的,可变的需要加 mut
fn greet(&self) -> String {
format!("Hi {}", self.name)
}
fn up_age(&mut self, n:i32) {
self.age += n;
}
// self 一般用来销毁
fn drop_self(self) {
println!("drop self");
}
}
fn main() {
let mut person: Person = Person::new("david".to_string(), 30);
println!("{:#?}", person);
println!("{}", person.greet());
person.up_age(3);
println!("{}", person.age);
person.drop_self();
}
/**
* 元组 tuple
* 相似类型有数组、切片,但在 rust 中不常用,常用 Vector
*
* - 匿名存储数据
* - 不可变
*
* 元组的用处
* - 函数返回
* - 提取变量
*/
#[derive(Debug)]
enum In {
Oh
}
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 {}", x, y, z);
let (man, action) = ("david", In::Oh);
println!("man: {}, in: {:?}", man,action);
}
/**
*
* OwnerShip
*
* - move & borrowed
* - clone & copy
* - reference
* - lifetime
*
*
* ownership model
*
* ownership 规则
* - 每个值都有一个变量称为所有者
* - 每个值同时只能有一个所有者
* - 当所有者超出作用域时,值被销毁
*
* Stack 和 Heap
* - Stack 存储已知的大小的数据;快;基础数据类型等
* - Heap 存储未知大小的数据;慢;Struct 等
**/
/**
* move 可理解为
*
* 浅拷贝 + 失效
*
* let a = "ff".to_string();
* let b = a; // a 失效
*
*
* copy/clone 可理解为
*
* 深度拷贝 开辟新的空间
*/
#[derive(Debug)]
struct A {
a: i32,
}
fn main() {
let a: &str = "str";
let b: &str = a;
println!("{}, {}", a, b);
// let p: String = "str".to_string();
// let q: String = p;
// 此时 p 会报错: borrow of moved value: `p` value borrowed here after move
// println!("{}, {}", p, q);
// let m: A = A{a: 7};
// let n = m;
// // 此时 m 会报错:borrow of moved value: `m` value borrowed here after move
// println!("{:?}, {:?}", m, n);
}
/**
* 引用和可变引用
*
* & 和 &mut
*
*
* 在同一作用域下,对某一块数据:
* - 可以有多个不可变引用
* - 只能有一个可变的引用
* - 不能同时拥有一个可变引用和一个不可变引用
*/
struct A {
a: i32
}
fn r(a: A) {
println!("{}", a.a);
}
fn rr(a: &A) {
println!("{}", a.a);
}
fn rrr(a: &mut A) {
a.a = 74520;
}
fn main() {
let a = A {a: 4};
println!("{}", a.a);
rr(&a);
println!("{}", a.a);
r(a);
// 报错 borrow of moved value: `a` value borrowed here after move
// println!("{}", a.a);
let mut b = A {a: 3};
println!("{}", b.a);
rrr(&mut b);
println!("{}", b.a);
let mut s = "ke".to_string();
let ss = &mut s;
let s = &mut s; // cannot borrow `s` as mutable more than once at a time second mutable borrow occurs here
ss.push('h');
}
/**
* copy & clone
*
* 二者都是 trait 特质
*/
#[derive(Debug, Clone)]
struct Person {
name: String,
age: i32
}
fn main() {
let person = Person {
name: "david".to_string(),
age: 9
};
let ok: Person = person.clone();
println!("{:?}, {:?}", person, ok);
}
#[derive(Debug, Clone, Copy)]
struct Person<'a> {
name: &'a str,
age: i32
}
fn main() {
let person = Person {
name: "david",
age: 9
};
let ok: Person = person;
println!("{:?}, {:?}", person, ok);
}
/**
* 生命周期 lifetime
*
* 避免 dangling reference
* rust 中所有的引用都有自己的生命周期,表示引用有效的作用域
* 一般为隐式的,但不可推断时会保错,需要手动标注生命周期
*
* 一般不要用 'static
*
* 省略规则
* - 每个引用类型的参数都有自己的生命周期
* - 只有一个输入生命周期参数,那么输入生命周期就为该生命周期
* - 有 &self 或 &mut self,那么输出生命周期就为该 self 生命周期
*/
// a, b 和返回值是同一个作用域,以最短的生命周期为有效
fn longest<'a>(a: &'a str, b: &'a str) -> &'a str {
if a.len() > b.len() {
a
} else {
b
}
}
fn main() {
}
/**
* 常用数据类型 String
*
* &str:String slices 不可变的,放在栈上
* let cat = "cat";
*
*
* String object 放在堆上
* let dog = String::new();
* let dog = String::from("sd");
* let dog = "s".to_string();
* 通过 format! 生成
*/
/**
* String 方法
len()
push 字符
push_str
replace
*/
fn main() {
let cat: &str = "cat";
println!("cat: {cat}");
let dog = String::new();
println!("dog: {dog}");
let dog = String::from("sd");
println!("dog: {dog}");
let mut dog = "s".to_string();
dog.push('f');
dog.push_str("david");
println!("dog: {dog}");
println!("{}", dog.replace("id", "-dd-"));
let dog = format!("{}", 1);
println!("dog: {dog}");
println!("dog len: {}", dog.len());
}
/**
* 常用数据类型 Vector 可变数组
*
* 构造
* let arr = Vec::new();
* let arr = vec![1, 2];
* let arr = vec![1;20];
*
* 方法
* push & remove
*/
fn main() {
let mut arr1: Vec<i32> = Vec::new();
arr1.push(1);
println!("{:?}", arr1);
let mut arr2: Vec<i32> = vec![1,2];
arr2.push(3);
println!("{:?}", arr2);
let mut arr3: Vec<i32> = vec![1;20];
arr3.remove(0);
println!("{:?}", arr3);
// [1]
// [1, 2, 3]
// [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
// println!("{}", arr3[21]); // 越界运行会报错
match arr3.get(21) {
Some(item) => println!("{}", item),
None => {}
}
for item in arr3.iter() {
println!("{}", item);
}
}
/**
* HashMap
*
* 散列函数把消息或数据压缩为摘要,使得数据量变小,将数据的格式固定下来。
* 该函数将数据打乱混合,重新创建一个叫做散列值(hash values, hash codes, hash sums 或 hashes)的指纹
*
* HashMap 由 链表 + 数组 组成,他的底层结构是一个数组,而数组的元素是一个单向链表
*
* rust 中 HashMap 的键可以是布尔型、整型、字符串或任意实现了 Eq 和 Hash trait 的其他类型
* HashMap 也是可增长的,但 HashMap 在占据了多余空间时还可以缩小自己
*/
use std::collections::HashMap;
fn main () {
let mut string_map: HashMap<&str, i32> = HashMap::new();
string_map.insert("david", 51);
string_map.insert("david2", 56);
println!("{:#?}", string_map);
match string_map.get(&"david2") {
Some(&age) => println!("david2 is {} years old", age),
None => {},
}
string_map.remove(&"david");
for pair in string_map.into_iter() {
println!("{}, {}", pair.0, pair.1)
}
}
/**
* traits
*
* 与接口和抽象类类似
* 给结构体添加定义的行为
*
* impl trait_demo for struct_demo
*
* 返回特质时需要加 Box
* fn get_trait() -> Box<dyn trait_name>
*/
struct A {
name: String
}
impl Person for A {
fn new(awesome: String) -> Self {
A {
name: awesome
}
}
fn language(&self) -> &str {
"A"
}
}
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!("a hello world, {}", self.name);
}
}
trait Person {
fn new(awesome: String) -> Self;
fn language(&self) -> &str;
fn say_hello(&self) {
println!("hello world");
}
}
fn main() {
let a: A = A::new("david_a".to_string());
let b: B = B::new("david_b".to_string());
a.say_hello();
b.say_hello();
}
/**
* generics
*
* 泛型时程序设计语言的一种风格或范式
* 在强类型程序设计语言编写代码时使用一些以后才指定的类型,在实例化时作为参数声明这些类型
*/
trait Bark {
fn bark(&self) -> String;
}
struct Dog {
species: String
}
struct Cat {
color: 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".to_string()};
bark(dog);
let cat = Cat { color: "white".to_string() };
bark(cat); // the trait bound `Cat: Bark` is not satisfied
}
目录