打印
#[derive(Debug)] // 有了这才能通过 {:?} {:#?} debug
struct Complex {
real: f64,
imag: f64,
}
impl fmt::Display for Complex {
// 默认泛型容器没有实现,要手动实现才能使用 {} 打印
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "x: {}, y: {}", self.real, self.imag)
}
}
/// this is doc comment
/// ...
fn print() {
/* format!();print!();println!();eprint!();eprintln!(); */
let variable = 1;
println!("{} 为占位符", variable);
println!(
"named argument: {subject} {verb} {object}",
subject = "A",
verb = "hava",
object = "ball"
);
println!("Base 10: {}", 69420); //69420
println!("Base 2 (binary): {:b}", 69420); //10000111100101100
println!("Base 8 (octal): {:o}", 69420); //207454
println!("Base 16 (hexadecimal): {:x}", 69420); //10f2c
println!("Base 16 (hexadecimal): {:X}", 69420); //10F2C
println!(
"打印详细信息:{o} {o:?} {o:#?}",
o = Complex {
real: 1.1,
imag: 3.2
}
); // 默认不可打印,实现 Debug 接口才可
}
// 可打印列表
struct List(Vec<i32>);
impl fmt::Display for List {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let vec = &self.0;
write!(f, "[")?; // ? 用于处理 Result 返回值,出错则直接结束函数返回error,否则继续
for (i, ele) in vec.iter().enumerate() {
if i != 0 {
write!(f, ",")?;
}
write!(f, "{} : {}", i, ele)?;
}
write!(f, "]")
}
}
更多格式见:https://doc.rust-lang.org/std/fmt/
基本
操作符类似C
fn main() {
// Integer addition
println!("1 + 2 = {}", 1u32 + 2);
// Integer subtraction
println!("1 - 2 = {}", 1i32 - 2);
// TODO ^ Try changing `1i32` to `1u32` to see why the type is important
// Short-circuiting boolean logic
println!("true AND false is {}", true && false);
println!("true OR false is {}", true || false);
println!("NOT true is {}", !true);
// Bitwise operations
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);
// Use underscores to improve readability!
println!("One million is written as {}", 1_000_000u32);
}
tuple
fn fun() {
let tuple_of_tuples = ((1u8, 2u16, 2u32), (4u64, -1i8), -2i16);
println!("tuple of tuples: {:?}", tuple_of_tuples);
let matrix = Matrix(1.1f32, 1.2f32, 1.3, 1.4);
println!("Matrix:\n{}", matrix);
println!("Transpose:\n{}", transpose(matrix));
}
struct Matrix(f32, f32, f32, f32);
impl fmt::Display for Matrix {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "( {} {} )\n( {} {})", self.0, self.1, self.2, self.3)
}
}
fn transpose(matrix: Matrix) -> Matrix {
let e0 = matrix.0;
let e1 = matrix.1;
let e2 = matrix.2;
let e3 = matrix.3;
Matrix(e0, e1, e3, e2)
}
切片:占用两个字,一个为指向数据的指针,另一个为长度。
fn analyze_slice(slice: &[i32]) {
println!("first element of the slice: {}", slice[0]);
println!("the slice has {} elements", slice.len());
}
fn fun() {
let arr1: [i32; 5] = [1,2,3,4,5];
let arr2: [i32; 10] = [0; 10];
println!("{} {} {}", arr1[0], arr2.len(), std::mem::size_of_val(&arr1));
// 数组被自动借用为切片,空切片:&[]
analyze_slice(&arr1);
analyze_slice(&arr2[3 .. 6]);
// 使用 get 方法得到被 Option 包裹的数据,可以使用 match 或 expect 方法处理
for i in 0..arr2.len() + 1 {
match arr2.get(i) {
Some(val) => println!("{}: {}", i, val),
None => println!("over the bound!"),
}
}
}
结构体 枚举类型 别名 静态变量
结构体
// 无字段可用于泛型
struct Unit;
// struct tuple 即命名数组
struct Pair(i32, i32);
#[derive(Debug)]
struct Point {
x: f32,
y: f32,
}
struct Rectangle {
top_left: Point,
bottom_right: Point,
}
impl Rectangle {
fn area(&self) -> f32 {
(self.bottom_right.x - self.top_left.x) * (self.bottom_right.y - self.top_left.y)
}
}
fn square(p: Point, l: f32) -> Rectangle {
Rectangle {
bottom_right: Point { // 注意这里要在 top_left 之前声明,否则p被 borrowed ,就无法再使用
x: p.x + l,
y: p.y + l,
},
top_left: p,
}
}
fn fun() {
let point1 = Point{x:1.1, y:1.2};
// 使用结构体更新语法引用其他结构体数据
let point2 = Point{x:2.1, ..point1};
// destructure
let Point { x: left_edge, y: top_edge } = point2;
let _rec = Rectangle {
top_left: Point { x: left_edge, y: top_edge },
bottom_right: point1, // point1 be borrowed
};
}
枚举类型,use 与命名空间
enum Event {
PageLoad, // unit struct
KeyPress(char), // struct tuple
Paste(String),
Click { x: i64, y: i64 }, // struct
}
fn inspect(event: Event) {
// 使用 use 后无需使用命名空间
use crate::Event::{KeyPress, PageLoad}; // use create::Event::*;
match event {
PageLoad => println!("page loaded"),
KeyPress(c) => println!("pressed '{}'.", c),
Event::Paste(s) => println!("pasted \"{}\".", s),
Event::Click { x, y } => {
println!("clicked at x={}, y={}.", x, y);
}
}
}
#![allow(dead_code)]
use std::fmt::Display;
use crate::List::*;
enum List<T: Display> {
Cons(T, Box<List<T>>),
Nil,
}
impl<T: Display> List<T> {
fn new() -> List<T> {
List::Nil
}
// self 代表对象,所有权会移交
fn prepend(self, elem: T) -> List<T> {
List::Cons(elem, Box::new(self))
}
// &self 代表引用,所有权不会移交
fn len(&self) -> u64 {
match self {
List::Cons(_, tail) => 1 + tail.len(),
Nil => 0,
}
}
fn stringify(&self) -> String {
match self {
List::Cons(head, tail) => {
format!("{}, {}", head, tail.stringify())
}
List::Nil => {
format!("Nil")
}
}
}
}
fn main() {
let mut list = List::<i32>::new();
list = list.prepend(1);
list = list.prepend(2);
list = list.prepend(3);
println!("{}", list.stringify()); // 3, 2, 1, Nil
}
enum 类C用法
// enum with implicit discriminator (starts at 0)
enum Number {
Zero,
One,
Two,
}
// enum with explicit discriminator
enum Color {
Red = 0xff0000,
Green = 0x00ff00,
Blue = 0x0000ff,
}
fn main() {
// `enums` can be cast as integers.
println!("zero is {}", Number::Zero as i32);
println!("one is {}", Number::One as i32);
println!("roses are #{:06x}", Color::Red as i32);
println!("violets are #{:06x}", Color::Blue as i32);
}
别名
type AliasType = SomeType;
静态变量
- const:不可变,常用
- static:可能是 mut 类型,被推断为静态生命周期 'static,访问修改都是 unsafe 的
类型转换
使用 use 显现类型转换,rust 没有隐式类型转换
let decimal = 65.4321_f32;
let integer = decimal as u8;
let char = integer as char;
// 300.0 as u8 is 255
println!(" 300.0 as u8 is : {}", 300.0_f32 as u8);
// -100.0 as u8 is 0
println!("-100.0 as u8 is : {}", -100.0_f32 as u8);
// nan as u8 is 0
println!(" nan as u8 is : {}", f32::NAN as u8);
内置类型转换 From Into
let my_str = "hello";
let my_string = String::from(my_str);
struct Number {
value: i32,
}
impl From<i32> for Number {
fn from(item: i32) -> Self {
Number { value: item }
}
}
let num = Number::from(30);
let int = 5;
let num: Number = int.into();
try_from / try_into 返回一个 Result
#[derive(Debug, PartialEq)]
struct EvenNumber(i32);
impl TryFrom<i32> for EvenNumber {
type Error = ();
fn try_from(value: i32) -> Result<Self, Self::Error> {
if value % 2 == 0 {
Ok(EvenNumber(value))
} else {
Err(())
}
}
}
使用 Display 转为 String
使用字符串实现的 FromStr 接口的 parse 方法将 String 转为其他类型
let parsed: i32 = "5".parse().unwrap();
let turbo_parsed = "10".parse::<i32>().unwrap();
控制流
let x = if n < 100.0 {
1
} else if n < 10.0 {
2
} else {
3
};
// loop 死循环 可搭配 break continue
fn main() {
'outer: loop {
println!("Entered the outer loop");
'inner: loop {
println!("Entered the inner loop");
// This breaks the outer loop
break 'outer;
}
println!("This point will never be reached");
}
println!("Exited the outer loop");
}
/*
Entered the outer loop
Entered the inner loop
Exited the outer loop
*/
let result = loop {
counter += 1;
if counter == 10 {
break counter * 2;
}
};
while 搭配布尔语句
for n in 1..101 {
}
for n in 1..=100 {
}
let names = vec!["Bob", "Frank", "Ferris"];
// 元素被借用,循环后可再用
for name in names.iter() {
match name {
&"Ferris" => println!("There is a rustacean among us!"),
_ => println!("Hello {}", name),
}
}
// 元素可以被原地修改,循环后可用
for name in names.iter_mut() {
*name = match name {
&mut "Ferris" => "There is a rustacean among us!",
_ => "Hello",
}
}
// 元素被移动,循环后不可再用
for name in names.into_iter() {
match name {
"Ferris" => println!("There is a rustacean among us!"),
_ => println!("Hello {}", name),
}
}
match destructuring
match number {
1 => println!("One!"),
2 | 3 | 5 | 7 | 11 => println!("This is a prime"),
13..=19 => println!("A teen"),
_ => println!("Ain't special"), // 处理其他情况,不可缺少
}
let arr = 数组或切片;
match arr {
[0, second, third] => print!(),
[1, _, third] => print!(),
// 绑定一些忽略一些
[2, second, ..] => print!(),
// 将剩余的绑定到数组或切片
[3, second, tail @ ..] => print!(),
[first, middle @ .., last] => print!(),
}
match tuple {
(0, x, y) if x > 0 => println!(""), // 分支守卫
(3, .., 4) => println!(""),
_ => print!(),
}
let reference = &4;
match reference {
&val => print!("这里变量被解引用"),
}
match value {
ref r => print!("创建新引用"),
}
match value {
ref mut m => print!("可变引用"),
}
match value {
Foo { x: 1, y: a} => print!(""),
Foo { x: a, y: 1} => print!(""),
}
// 使用 @ 绑定对象
match age() {
0 => xx,
n @ 1 ..= 12 => xx,
n @ 13 ..= 19 => xx,
n => xx,
}
闭包
fn main() {
/****************** borrow / reference *******************/
let mut outer_var = 42;
let closure_annotated = |i: i32| -> i32 { i + outer_var }; // immutrably borrow
let mut closure_inferred = |i| outer_var += i; // mutably borrow
closure_inferred(1); // 有了这句使用后才能推断出闭包类型
// println!("{}", outer_var); // 在其他借用没有结束时借用,会报错
closure_inferred(1);
println!("{}", outer_var); // 此处不会报错
/****************** move *******************/
let movable = Box::new(3);
let consume = || {
println!("`movable`: {:?}", movable);
std::mem::drop(movable); // drop函数需要传入move值,此处发生 move
};
consume();
// consume(); 因为变量只能move一次,所以再次调用会报错
let contains = move |needle| haystack.contains(needle); // 在 | 前使用 move 关键字,强制move
}
当闭包作为函数参数时,需要用接口指明 参数为闭包 还有 闭包的参数捕获方式:Fn
FnMut
FnOnce
。权限逐渐变严格,FnOnce接收更宽松的两类接口,FnMut也可传入Fn接口
fn apply<F>(f: F)
where
F: FnOnce(),
{
f();
}
fn main() {
use std::mem;
let mut w = "hello".to_owned(); // create owned data
let f = || {
mem::drop(w);
};
apply(f); // 函数f的参数是 move 来的,apply中必须要用 FnOnce
}
当闭包作为输出时要用 impl 和接口
指明类型,同时还要用 move
将捕获变量转移出,否者在函数结束后引用变量销毁。
fn create_fn() -> impl Fn() {
let text = "Fn".to_owned();
move || println!("This is a: {}", text)
}
fn create_fnmut() -> impl FnMut() {
let text = "FnMut".to_owned();
move || println!("This is a: {}", text)
}
fn create_fnonce() -> impl FnOnce() {
let text = "FnOnce".to_owned();
move || println!("This is a: {}", text)
}
fn main() {
let fn_plain = create_fn();
let mut fn_mut = create_fnmut();
let fn_once = create_fnonce();
fn_plain();
fn_mut();
fn_once();
}
函数式编程
// Functional approach 所有奇数的平方
let sum_of_squared_odd_numbers: u32 =
(0..).map(|n| n * n) // All natural numbers squared
.take_while(|&n_squared| n_squared < upper) // Below upper limit
.filter(|&n_squared| is_odd(n_squared)) // That are odd
.sum(); // Sum them
println!("functional style: {}", sum_of_squared_odd_numbers);
Diverging functions
不会正常返回的函数
fn foo() -> ! {
panic!("This call never returns.");
}
#![feature(never_type)]
fn main() {
let x: ! = panic!("This call never returns.");
println!("You will never see this line!");
}
fn main() {
fn sum_odd_numbers(up_to: u32) -> u32 {
let mut acc = 0;
for i in 0..up_to {
// Notice that the return type of this match expression must be u32
// because of the type of the "addition" variable.
let addition: u32 = match i%2 == 1 {
// The "i" variable is of type u32, which is perfectly fine.
true => i,
// On the other hand, the "continue" expression does not return
// u32, but it is still fine, because it never returns and therefore
// does not violate the type requirements of the match expression.
false => continue,
};
acc += addition;
}
acc
}
println!("Sum of odd numbers up to 9 (excluding): {}", sum_odd_numbers(9));
}
模块
模块默认都是私有的,使用 pub 关键字修饰后其他模块才可见。
结构体的字段与方法也都默认私有。
mod my_mod {
fn private_fun(){}
pub fn public_fun(){}
pub mod nested {
pub(in crate::my_mod) fn public_in_given_mod(){}
pub(super) fn public_in_super_super_mod(){}
pub(crate) fn same_as_private(){}
}
}
use 声明
use crate::deeply::nested::{
my_first_function,
my_second_function,
AndATraitType
};
use deeply::nested::function as other_function;
super & self
mod mod1 {
pub(super) fn fun1() {
println!("fun1");
}
}
mod mod2 {
mod mod3 {
pub fn fun2() {
println!("fun2");
}
}
fn fun() {
self::mod3::fun2();
super::mod1::fun1();
}
}
$ tree .
.
├── my
│ ├── inaccessible.rs my::nested::xxx
│ └── nested.rs my::nested::xxx
├── my.rs my::xxx
└── split.rs
在 split.rs 文件头部输入 mod my; 使 my.rs 内部自动创建模块my并插入 my.rs 的内容
在 my.rs 文件头部插入 mod inaccessible; 和 pub mod nested;
|--main.rs 通过 pub mod util; 引入util模块
|--util.rs
|--util/
|--mod.rs
|--math.rs
注意:utils.rs 和 util/mod.rs 内容都是util模块下的内容;二者同时存在会冲突
Cargo & Crates
crates.io: Rust Package Registry https://crates.io
cargo new foo # A binary
cargo new --lib bar # A library
cargo build
cargo run
.
├── bar
│ ├── Cargo.toml
│ └── src
│ └── lib.rs # 库
│ └── main.rs # 可执行文件
└── foo
├── Cargo.toml
└── src
└── lib.rs # 库
└── main.rs # 可执行文件
一个 crate 包中生成多个可执行文件
foo
├── Cargo.toml
└── src
├── main.rs
└── bin
└── my_other_bin.rs
# cargo build 生成默认文件
# cargo build --bin my_other_bin 指定可执行文件,文件名为 my_other_bin
Attributes
修饰crate、条件编译、格式化、链接、单元测试、压力测试、类宏属性
#![allow(dead_code)] // #! 开头,修饰crate
// 三种修饰 mod fn 的格式
#[attribute = "value"]
#[attribute(key = "value")]
#[attribute(value)]
cfg 代指 configure,在使用 rustc 编译时可以通过 --cfg 指定
#[cfg(...)]
条件编译cfg!(...)
在运行时返回布尔值
#[cfg(target_os = "linux")]
fn are_you_on_linux() {
println!("You are running linux!");
}
#[cfg(not(target_os = "linux"))]
fn are_you_on_linux() {
println!("You are *not* running linux!");
}
fn main() {
are_you_on_linux();
println!("Are you sure?");
if cfg!(target_os = "linux") {
println!("Yes. It's definitely linux!");
} else {
println!("Yes. It's definitely *not* linux!");
}
}
标签:rs,self,语法,let,println,rus,my,fn From: https://www.cnblogs.com/zhh567/p/17201586.html