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);
        }
        _ => {}
    }
}
  1. Integer
    分为有符号型和无符号型, i32, usize等
  2. Boolean
    true,false
  3. Character字符类型
    单引号,let a = 'a'; let smile = '\u{1F601}'
  4. &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);

控制流程

  1. 循环
    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;
        }
    }
}
  1. 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等。

  1. 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);
  1. 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);
}
posted @   saulstavo  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示