Rust总结:基本类型 Primitives

原文:https://rustwiki.org/zh-CN/rust-by-example/primitives.html

标量类型(scalar type)

  • 有符号整数(signed integers):i8、i16、i32、i64、i128 和 isize(指针宽度)
  • 无符号整数(unsigned integers): u8、u16、u32、u64、u128 和 usize(指针宽度)
  • 浮点数(floating point): f32、f64
  • char(字符):单个 Unicode 字符,如 ‘a’,’α’ 和 ‘∞’(每个都是 4 字节)
  • bool(布尔型):只能是 true 或 false
  • 单元类型(unit type):()。其唯一可能的值就是 () 这个空元组
  • 尽管单元类型的值是个元组,它却并不被认为是复合类型,因为并不包含多个值。
fn main() {
    // 整数相加
    println!("1 + 2 = {}", 1u32 + 2);

    // 整数相减
    println!("1 - 2 = {}", 1i32 - 2);
    // 试一试 ^ 尝试将 `1i32` 改为 `1u32`,体会为什么类型声明这么重要

    // 短路求值的布尔逻辑
    println!("true AND false is {}", true && false);
    println!("true OR false is {}", true || false);
    println!("NOT true is {}", !true);

    // 位运算
    println!("0011 AND 0101 is {:04b}", 0b0011u32 & 0b0101);
    println!("0011 OR 0101 is {:04b}", 0b0011u32 | 0b0101);
    println!("0011 XOR 0101 is {:04b}", 0b0011u32 ^ 0b0101);
    println!("1 << 5 is {}", 1u32 << 5);
    println!("0x80 >> 2 is 0x{:x}", 0x80u32 >> 2);

    // 使用下划线改善数字的可读性!
    println!("One million is written as {}", 1_000_000u32);
}

复合类型(compound type)

  • 数组(array):如 [1, 2, 3]
  • 元组(tuple):如 (1, true)
// 元组可以充当函数的参数和返回值
fn reverse(pair: (i32, bool)) -> (bool, i32) {
    // 可以使用 `let` 把一个元组的成员绑定到一些变量
    let (integer, boolean) = pair;

    (boolean, integer)
}

// 在 “动手试一试” 的练习中要用到下面这个结构体。
#[derive(Debug)]
struct Matrix(f32, f32, f32, f32);

fn main() {
    // 包含各种不同类型的元组
    let long_tuple = (1u8, 2u16, 3u32, 4u64,
                      -1i8, -2i16, -3i32, -4i64,
                      0.1f32, 0.2f64,
                      'a', true);

    // 通过元组的下标来访问具体的值
    println!("long tuple first value: {}", long_tuple.0);
    println!("long tuple second value: {}", long_tuple.1);

    // 元组也可以充当元组的元素
    let tuple_of_tuples = ((1u8, 2u16, 2u32), (4u64, -1i8), -2i16);

    // 元组可以打印
    println!("tuple of tuples: {:?}", tuple_of_tuples);

    // 但很长的元组无法打印
    // let too_long_tuple = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13);
    // println!("too long tuple: {:?}", too_long_tuple);
    // 试一试 ^ 取消上面两行的注释,阅读编译器给出的错误信息。

    let pair = (1, true);
    println!("pair is {:?}", pair);

    println!("the reversed pair is {:?}", reverse(pair));

    // 创建单元素元组需要一个额外的逗号,这是为了和被括号包含的字面量作区分。
    println!("one element tuple: {:?}", (5u32,));
    println!("just an integer: {:?}", (5u32));

    // 元组可以被解构(deconstruct),从而将值绑定给变量
    let tuple = (1, "hello", 4.5, true);

    let (a, b, c, d) = tuple;
    println!("{:?}, {:?}, {:?}, {:?}", a, b, c, d);

    let matrix = Matrix(1.1, 1.2, 2.1, 2.2);
    println!("{:?}", matrix)

}

数组和切片

  • 数组(array)
    • 是一组拥有相同类型 T 的对象的集合
      • 内存中是连续存储的
      • 数组使用中括号 [] 来创建
      • 且它们的大小在编译时会被确定
      • 数组的类型标记为 [T; length](译注:T 为元素类型,length 表示数组大小)
  • 切片(slice)
    • 类似数组
    • 但其大小在编译时是不确定的。
    • 切片是一个双字对象(two-word object),第一个字是一个指向数据的指针,第二个字是切片的长度。这个 “字” 的宽度和 usize 相同,由
    • 类型标记为 &[T]
// 此函数借用一个 slice
fn analyze_slice(slice: &[i32]) {
    println!("first element of the slice: {}", slice[0]);
    println!("the slice has {} elements", slice.len());
}

fn main() {
    // 定长数组(类型标记是多余的)
    let xs: [i32; 5] = [1, 2, 3, 4, 5];

    // 所有元素可以初始化成相同的值
    let ys: [i32; 500] = [0; 500];

    // 下标从 0 开始
    println!("first element of the array: {}", xs[0]);
    println!("second element of the array: {}", xs[1]);

    // `len` 返回数组的大小
    println!("array size: {}", xs.len());

    // 数组是在栈中分配的
    println!("array occupies {} bytes", mem::size_of_val(&xs));

    // 数组可以自动被借用成为 slice
    println!("borrow the whole array as a slice");
    analyze_slice(&xs);

    // slice 可以指向数组的一部分
    println!("borrow a section of the array as a slice");
    analyze_slice(&ys[1 .. 4]);

    // 越界的下标会引发致命错误(panic)
    // println!("{}", xs[5]);
}

Rust 总结:格式化

https://github.com/mattwhatsup/rust-practice-and-notes/tree/main/print-and-format
https://rustwiki.org/zh-CN/rust-by-example/hello/print.html

相关模块

std::fmt

  • format!:将格式化文本写到字符串。
  • print!:与 format! 类似,但将文本输出到控制台(io::stdout)。
  • println!: 与 print! 类似,但输出结果追加一个换行符。
  • eprint!:与 print! 类似,但将文本输出到标准错误(io::stderr)。
  • eprintln!:与 eprint! 类似,但输出结果追加一个换行符。
  • fmt::Debug:使用 {:?} 标记。格式化文本以供调试使用。
  • fmt::Display:使用 {} 标记。以更优雅和友好的风格来格式化文本。

一些常见格式的罗列

fn main() {
    println!("{}", 1); // 默认用法,打印Display
    println!("{:o}", 9); // 八进制
    println!("{:x}", 255); // 十六进制 小写
    println!("{:X}", 255); // 十六进制 大写
    println!("{:p}", &0); // 指针
    println!("{:b}", 15); // 二进制
    println!("{:e}", 10000f32); // 科学计数(小写)
    println!("{:E}", 10000f32); // 科学计数(大写)
    println!("{:?}", "test"); // 打印Debug
    println!("{:#?}", ("test1", "test2")); // 带换行和缩进的Debug打印
    println!("{a} {b} {b}", a = "x", b = "y"); // 命名参数


    assert_eq!(format!("Hello {:<5}!", "x"),  "Hello x    !"); // <右边界宽度
    assert_eq!(format!("Hello {:-<5}!", "x"), "Hello x----!"); // <右边界宽度+填充
    assert_eq!(format!("Hello {:^5}!", "x"),  "Hello   x  !"); // ^居中
    assert_eq!(format!("Hello {:>5}!", "x"),  "Hello     x!"); // >右边界宽度

    println!("Hello {:+}", 5); // +显示正号
    println!("{:#x}!", 27); // #显示十六进制
    assert_eq!(format!("Hello {:05}!", 5),  "Hello 00005!"); // 宽度
    println!("{:#09x}!", 27); // 十六进制数字宽度
    println!("Hello {0} is {1:.5}", "x", 0.01); // 小数位

    // $代入符号
    println!("Hello {0} is {1:.5}", "x", 0.01);
    // 0的位置是5,1的位置是x,2的位置是0.01
    println!("Hello {1} is {2:.0$}", 5, "x", 0.01);
    // 0的位置是x,1的位置是5,2的位置是0.01
    println!("Hello {0} is {2:.1$}", "x", 5, 0.01);
    // *统配代入符号
    // 0的位置是x,1的位置是5,2的位置是0.01
    println!("Hello {} is {:.*}",    "x", 5, 0.01);
    // 0的位置是5,1的位置是x,2的位置是0.01
    println!("Hello {1} is {2:.*}",  5, "x", 0.01);

    // 转义{}
    assert_eq!(format!("Hello {{}}"), "Hello {}");
    assert_eq!(format!("{{ Hello"), "{ Hello");
}

Debug trait

#[derive(Debug)] 所有类型都能推导fmt::Debug 的实现

// `derive` 属性会自动创建所需的实现,使这个 `struct` 能使用 `fmt::Debug` 打印。
#[derive(Debug)]
struct DebugPrintable(i32);

使用 {:#?} 美化打印

Display trait

fmt::Display 需要自己实现

// (使用 `use`)导入 `fmt` 模块使 `fmt::Display` 可用
use std::fmt;

// 定义一个结构体,咱们会为它实现 `fmt::Display`。以下是个简单的元组结构体
// `Structure`,包含一个 `i32` 元素。
struct Structure(i32);

// 为了使用 `{}` 标记,必须手动为类型实现 `fmt::Display` trait。
impl fmt::Display for Structure {
    // 这个 trait 要求 `fmt` 使用与下面的函数完全一致的函数签名
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // 仅将 self 的第一个元素写入到给定的输出流 `f`。返回 `fmt:Result`,此
        // 结果表明操作成功或失败。注意 `write!` 的用法和 `println!` 很相似。
        write!(f, "{}", self.0)
    }
}

如果想实现 {:b} 打印二进制则需要自己实现 std::fmt::Binary

Rust学习的关键资源

⭐️ Rust-Learning repo https://github.com/ctjhoa/rust-learning

官方教程(号称The Book)https://doc.rust-lang.org/stable/book/
中文版 https://kaisery.github.io/trpl-zh-cn/ https://rustwiki.org/zh-CN/book/

Easy Rust 用比较简单的英语写的教程,内容也较简单一些(入门)
https://dhghomon.github.io/easy_rust/Chapter_0.html

菜鸟Rust教程 https://www.runoob.com/rust/rust-tutorial.html

Rust By Example https://doc.rust-lang.org/rust-by-example/hello.html
⭐️ 中文版 https://rustwiki.org/zh-CN/rust-by-example/index.html

⭐️ Rust Cookbook https://rust-lang-nursery.github.io/rust-cookbook/

中文版:https://rustwiki.org/zh-CN/rust-cookbook

⭐️ Rust By Practice( Rust 练习实践 ) https://zh.practice.rs/why-exercise.html

⭐️ Rust圣经 https://course.rs/about-book.html

Rustc Book https://doc.rust-lang.org/rustc/index.html

Rust 🦀 and WebAssembly https://rustwasm.github.io/book/

The wasm-bindgen Guide https://rustwasm.github.io/wasm-bindgen/introduction.html

Rust参考手册:

英文 https://doc.rust-lang.org/reference/introduction.html

中文 https://rustwiki.org/zh-CN/reference/introduction.html

Rust 宏小册 https://zjp-cn.github.io/tlborm/

Rust 中的异步编程 https://huangjj27.github.io/async-book/index.html

Rust 秘典(死灵书) https://nomicon.purewhite.io/intro.html

官方API文档 https://doc.rust-lang.org/std/index.html

标准库中文版 https://rustwiki.org/zh-CN/std/

优质Rust项目 https://github.com/rust-unofficial/awesome-rust
中文版 https://github.com/PuzzledAlien/awesome-rust-cn

Rust 中文资源 https://github.com/rust-lang-cn

Effective Rust https://www.lurklurk.org/effective-rust/cover.html

⭐️ RustGYM https://rustgym.com/ leetcode题目的rust解法

⭐️ Rustlings https://github.com/rust-lang/rustlings 官方出品的rust小练习,可以有针对的练习各个语法点

Rust Atomics and Locks:Low-Level Concurrency in Practice https://marabos.nl/atomics/

The Tauri Documentation Work-in-progress https://jonaskruckenberg.github.io/tauri-docs-wip/introduction.html

Comprehensive Rust https://google.github.io/comprehensive-rust/
安卓团队编写的为期四天的 Rust 课程,从基本语法到高级主题,最后一天还会讲到 Rust 如何用于安卓开发。

视频:Rust Linz https://www.youtube.com/watch?v=OhCjnyBc448&list=PL85XCvVPmGQgL3lqQD5ivLNLfdAdxbE_u

视频:The Rust Lang Book https://www.youtube.com/watch?v=OX9HJsJUDxA&list=PLai5B987bZ9CoVR-QEIN9foz4QCJ0H2Y8&index=1