Web Rust基础二

内容纲要

循环-流程控制

循环与其他语言大致相同:

//作用域块
    let a = {
        println!("ABC"); // 输出 ABC
        "DEF" // 作为这个花括号块的值
    }; // 分号不可省略
    println!("{}", a);

    //if else
    let a1 = 1;
    let b1 = 2;
    let c1 = if a1 < b1 {
        println!("true");
        "ABC"
    } else {
        println!("false");
        "DEF"
    };
    println!("{}", c1);
    let a2 = 1;
    let b2 = 2;
    if a2 < b2 {
        println!("if true 1");
    } else if a2 == b2 {
        println!("if true 2");
    }

    //match(类似switch)
    let week = "mon";
    let a3 = match week {
        "sun" => "weekend",
        "mon" | "tue" | "wed" | "thu" | "fri" => "weekday",
        "sat" => "weekend",
        _ => "illegal",
    }; //在表达式值为字符串或者数值时,末尾需要有默认分支 _ 。
    println!("{}", a3);
    //默认分支也可以用一个变量代替,这样,变量会被赋予表达式值
    let day = "xxx";
    match day {
        "sun" | "sat" => {
            println!("weekend");
        }
        "mon" | "tue" | "wed" | "thu" | "fri" => {
            println!("weekday");
        }
        other => {
            println!("{} is illegal", other);
        }
    }; //如果表达式的值为 bool 类型,枚举完 true 和 false 两个分支,不需要默认分支

    //while
    let mut num1 = 0;
    while num1 < 10 {
        println!("{}", num1);
        num1 += 1;
    }

    //loop
    let mut num2 = 0;
    loop {
        println!("{}", num2);
        num2 += 1;
        if num2 < 10 {
            continue;
        }
        break;
    }
    //loop表达式
    let mut num3 = 0;
    let num4 = loop {
        println!("{}", num3);
        num3 += 1;
        if num3 == 10 {
            break num3;
        }
    };
    println!("{}", num4);

    //for in循环
    let vec5 = vec![1, 2, 3];
    for v in &vec5 {
        println!("{}", v);
    }
    for v1 in 10..20 {
        println!("{}", v1);
    }

数据和处理

struct

struct 可以用于将几个不同类型的数据字段组合在一起,形成一个新的数据类型(与 C 语言的 struct 类似):

//...
struct Size {
    width: f32,
    height: f32,
}

// struct Size(f32, f32);//匿名

//...
let my_size = Size {
        width: 2.0,
        height: 3.4,
    };
let area = my_size.width * my_size.height;
println!("{}", area); 

取子字段可以只取引用:

//...
struct Product {
    name: String,
    price: u32,
}

//...
let my_product = Product {
        name: format!("Rust Book"),
        price: 30,
    };
let name: &str = &my_product.name;
let price = my_product.price;
println!("{}: {}", name, price);

分散赋值分为取值和取引用:

let Product { name, price } = my_product;
let Product { name, price } = &my_product;
let Product {
    ref mut name,
    ref price,
} = my_product;
let Product { ref name, .. } = my_product;

enum

enum 与很多编程语言的枚举类型不同,它的每个枚举项可以附加不同的数据:

//...
enum Shape {
    Rectangle {
        // Rectangle 附有 width 和 height 两个字段
        width: f32,
        height: f32,
    },
    Square(f32), // Square 只附有一个字段
    Round(f32),  // Round 只附有一个字段
    Point,       // Point 没附字段
}

//...
let my_shape1 = Shape::Rectangle {
        width: 30.0,
        height: 20.0,
    };
let area1 = match my_shape1 {
    Shape::Rectangle { width, height } => width * height,
    Shape::Square(len) => len * len,
    Shape::Round(r) => r * r * std::f32::consts::PI,
    Shape::Point => 0.,
};
println!("{}", area1);

如果只需要判断其中一种情况,可以使用 if let:

if let Shape::Rectangle { width, height } = my_shape {
    println!("Rectangle {}", width * height);
}

match 和 if let 也都可以只取引用,类似于分散赋值的做法:

match &my_shape {
    Shape::Rectangle { width, height } => {
        // width 和 height 是 &f32 类型
    }
    _ => {}
}
if let Shape::Rectangle { ref mut width, .. } = my_shape {
    // width 是 &mut f32 类型
}

数据表达式

表达现实中的数据时,一般是 struct 和 enum 的结合:struct 用于表达数据中永远存在的字段, enum 用于表达有时存在、有时不存在的数据字段。

例如,当前天气情况由气温和天气状况组成,其中天气状况可以是晴或者雨,如果是雨,它的降水概率可以为 0 至 100% ,这样的数据可以使用 struct 和 enum 表达为:

struct CurrentWeather {
    temperature: f32,
    condition: WeatherCondition,
}
enum WeatherCondition {
    Sunny,
    Rainy { probability: f32 },
}

debug

默认情况下, struct 和 enum 本身是不能使用 println! 和 dbg! 来输出的。加上 derive(Debug) 可以使得它能够被调试输出,此时 println! 中需要使用 {:?} 作为占位符:

#[derive(Debug)]
struct CurrentWeather {
    temperature: f32,
    condition: WeatherCondition,
}
#[derive(Debug)]
enum WeatherCondition {
    Sunny,
    Rainy { probability: f32 },
}
fn main() {
    let current_weather = CurrentWeather {
        temperature: 10.,
        condition: WeatherCondition::Sunny,
    };
    println!("{:?}", current_weather);
}

相等判定

另一个常用的标记是 derive(PartialEq) ,它可以使得两个同一类型的 struct 或 enum 被使用 == 来比较是否相等(意味着所有子字段都分别相等):

#[derive(Debug, PartialEq)]
struct CurrentWeather {
    temperature: f32,
    condition: WeatherCondition,
}
#[derive(Debug, PartialEq)]
enum WeatherCondition {
    Sunny,
    Rainy { probability: f32 },
}
fn main() {
    let a = CurrentWeather {
        temperature: 10.,
        condition: WeatherCondition::Sunny,
    };
    let b = CurrentWeather {
        temperature: 10.,
        condition: WeatherCondition::Sunny,
    };
    println!("{}", a == b);
}
``

## type

使用 type 语句可以创建一个 struct 或 enum 的别名,有时候可以缩短代码:

```rust
type CurWth = CurrentWeather;
type WthCond = WeatherCondition;
fn main() {
    let a = CurrentWeather {
        temperature: 10.,
        condition: WeatherCondition::Sunny,
    };
    let b = CurWth {
        temperature: 10.,
        condition: WthCond::Sunny,
    };
    println!("{}", a == b);
}

注意:这样只是生成了一个数据类型别名,并没有创建一个新的类型,因此只要原类型有 derive(PartialEq) ,使用原名和别名创建的数据是可以相互比较的。(在实际使用时,如果需要避免它们被相互比较或者混用,还是需要使用 struct 来重新定义一个新的类型。)

序列化

在实际使用时,数据往往需要经过序列化才能通过网络传输或与其他语言的代码交互。此时需要用到常用的序列化框架 serde 。以 JSON 格式的序列化为例,首先在 Cargo.toml 的 [dependencies] 中引入:

[dependencies]
serde = { version = "1", features = ["derive"] }
serde_json = "1"

然后对需要序列化的 struct 和 enum 添加 derive(Serialize) 、 derive(Deserialize) :

use serde::{Serialize, Deserialize};
#[derive(Debug, Serialize, Deserialize)]
struct CurrentWeather {
    temperature: f32,
    condition: WeatherCondition,
}
#[derive(Debug, Serialize, Deserialize)]
enum WeatherCondition {
    Sunny,
    Rainy { probability: f32 },
}
fn main() {
    let cw = CurrentWeather {
        temperature: 10.,
        condition: WeatherCondition::Sunny,
    };
    let cw_json = serde_json::to_string(&cw).unwrap();
    println!("{}", cw_json);
    let cw: CurrentWeather = serde_json::from_str(&cw_json).unwrap();
    println!("{:?}", cw);
}

code enjoy! 🐜🐜🐜

作者:indeex

链接:https://indeex.club

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

发表评论

您的电子邮箱地址不会被公开。