前言

无。


环境搭建

懒得开虚拟机了,所以不打算弄远程开发,先去官网网站搞一个Windows的开发环境,后续再弄Linux的部署环境,安装完成后输入版本查询命令验证安装:

PS C:\Users\admin> rustup -V
rustup 1.27.1 (54dd3d00f 2024-04-24)
info: This is the version for the rustup toolchain manager, not the rustc compiler.
info: The currently active `rustc` version is `rustc 1.81.0 (eeb90cda1 2024-09-04)`

Hello World

官方文档找到Hello World的栗子,先简单学习一手。

感觉文档问题很大,不先讲函数等等语法,先讲数组元组又讲它们怎么作为函数参数和返回值来用,返回语句还没有return,刚看到的时候懵了一下。

首先是新建一个Rust代码文件index.rs,然后写上hello world:

fn main() {
    println!("Hello WOrld!");
}

函数调用加了个感叹号,有点稀奇,再编译成可执行文件:

rustc .\index.rs

看到生成了一个exe可执行文件和一个pdb文件,运行exe文件即可输出Hello World:

PS D:\Code\Rust\study> .\index.exe
Hello WOrld!

看了下文档,println还支持参数代入和数字前缀填充等等功能:

fn main() {
    println!("Hello World, No.{n:>0wid$} {0}!", "Twings", n=1, wid=6);
}

得到结果:

PS D:\Code\Rust\study> .\index.exe
Hello World, No.000001 Twings!

结构体(类)

Rust的类即结构体:

#[derive(Debug)]
struct Person<'a>{
    name: &'a str, 
    age: u8, 
    birthday: &'a str, 
    power: i32
}

fn main() {
    let name = "Pite";
    let age = 28;
    let birthday = "20770707";
    let power = 5000;
    let pite = Person{name, age, birthday, power};
    println!("{:?}", pite);
}

通过配置#[derive(Debug)]可以打印结构体方便查看内容,打印结果:

PS D:\Code\Rust\study> .\index.exe     
Person { name: "Pite", age: 28, birthday: "20770707", power: 5000 }

也可以用更简洁一点的实例化方式:

let pite = Person{
    name: "Pite", 
    age: 28, 
    birthday: "20770707", 
    power: 5000
};

也可以通过定义函数的方式,给每种结构体自定义自己的打印方式:

use std::fmt::{self, Formatter, Display};

struct Person<'a>{
    name: &'a str, 
    age: u8, 
    birthday: &'a str, 
    power: i32
}

impl<'a> Display for Person<'a> {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{}, age: {}, birthday: {}, power: {}",
               self.name, self.age, self.birthday, self.power)
    }
}

fn main() {
    let name = "Pite";
    let age = 28;
    let birthday = "20770707";
    let power = 5000;
    let pite = Person{name, age, birthday, power};
    println!("{}", pite);
}

输出结果:

PS D:\Code\Rust\study> .\index.exe
Pite, age: 28, birthday: 20770707 , power: 5000

既然有类(结构体),那么自然也会有接口和类方法,Rust中的接口就是trait特质,可以在特质中定义抽象接口:

mod my_mod{
    use std::fmt::{self, Formatter, Display};

    pub trait Animal<'a, T> {
        fn new(name: &'a str, age: u8, birthday: &'a str, power: i32, secret: T) -> Self;
        fn get_name(&self) -> &'a str;
        fn get_age(&self) -> u8;
    }

    pub struct Person<'a, T> {
        name: &'a str, 
        age: u8, 
        birthday: &'a str, 
        power: i32,
        secret: T
    }

    impl<'a, T> Person<'a, T> {
        pub fn get_secret(&self) -> &T {
            &self.secret
        }
    }

    impl<'a, T> Animal<'a, T> for Person<'a, T> {
        fn new(name: &'a str, age: u8, birthday: &'a str, power: i32, secret: T) -> Self {
            Person{
                name: name,
                age: age,
                birthday: birthday,
                power: power,
                secret: secret
            }
        }
        fn get_name(&self) -> &'a str {
            self.name
        }
        fn get_age(&self) -> u8 {
            self.age
        }
    }

    pub struct Secret<'a> {
        pub content: &'a str
    }

    impl<'a, T: Display> Display for Person<'a, T> {
        fn fmt(&self, f: &mut Formatter) -> fmt::Result {
            write!(f, "{}, age: {}, birthday: {}, power: {}, secret: {}",
                self.name, self.age, self.birthday, self.power, self.secret)
        }
    }

    impl<'a> Display for Secret<'a> {
        fn fmt(&self, f: &mut Formatter) -> fmt::Result {
            write!(f, "/*{}*/",
                self.content)
        }
    }
}

use my_mod::Animal;

fn main() {
    let pite: my_mod::Person<my_mod::Secret> = my_mod::Animal::new(
        "Pite", 
        28, 
        "20770707", 
        5000,
        my_mod::Secret{content: "No way!"}
    );
    println!("{}", pite);
    println!("{}, {}, {}", pite.get_name(), pite.get_age(), pite.get_secret());
}

trait中定义的方法与trait本身具有相同的可见性配置(pub)。

搞了个模块+泛型+结构体+特质+方法的代码,一直debug,搞得头都大了,几个主要的bug:

  1. 模块内定义的特质,模块外调用其方法是要先使用use引入

  2. Display打印结构体时,除了该结构体本身,结构体中的结构体也要实现Display方法

  3. 乱七八糟的泛型和生命周期定义

变量

类型、枚举和生命周期先略过,等要用到再说。

变量以let关键字进行定义,虽然是强类型语言,但是编译时编译器会自行推断一些变量类型:

fn main() {
    let a = "abc";
    let b = 2333;
    let c = 2333.333;
    println!("An string: {:?}", a);
    println!("A integer: {:?}", b);
    println!("A integer too: {:?}", c as u32);
}

输出:

PS D:\Code\Rust\study> .\index.exe
An string: "abc"
A integer: 2333        
A integer too: 2333  

在rust中,变量默认是不可修改的:

fn main() {
    let a = 777;
    a = 4396;
}

尝试修改变量就会在编译时报错,无法为一个不可变变量赋值两次:

error[E0384]: cannot assign twice to immutable variable `a`

此时就需要将其定义为可变变量:

fn main() {
    let mut a = 777;
    a = 4396;
}

这样就不会有问题。

流程控制

if条件判断

条件判断略过。

循环

循环语句用的是loop:

fn main() {
    let x = 9u32;
    let mut y = 0u32;
    let res = loop {
        y += 1;
        if x * y == 81 {
            break x + y;
        }
    };
    println!("0x{:x}", res);
}

结果:

PS D:\Code\Rust\study> .\index.exe
0x12

loop循环可以按标签分层,还可以中断循环的同时返回一个值。

还有while循环,略过。

for循环稍有不同:

fn main() {
    for n in 1..=100 {
        println!("0x{:x}", n);
    }
}

用..=代替了其他语言下面的:

a=0;a<=100;a++

match模式匹配

类似其它语言的switch语句:

fn main() {
    for n in 1..=100 {
        match n {
            1 => println!("One!!!0x{:x}", n),
            2 | 4 | 6 | 8 => println!("Two!!!0x{:x}", n),
            20..=30 => println!("Three!!!0x{:x}", n),
            _ => println!("None!!!0x{:x}", n),
        }
    }
}

除了匹配某个确定的值,还可以设置多个值、区间和默认。


官网网址

官方文档


Web Rust

本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!

RustWeb开发入门
Python原型链污染