Rust-lang Book Ch1-3 Gettiing started, An example of Guessing Game, Common Concepts: Variable & Mutability, Data Types, Functions, Comments, Control Flow

Rust的意义

1. 编译器会拒绝具有潜在bug风险的代码,减少了单元测试时间,便于大规模合作

2. Rust自身携带的工具: Cargo帮助管理依赖包+编译+测试,Rustfmt能够统一代码风格,Rust Language Server内含IDE

3. 面向系统开发者,速度与稳定性兼备

 

资源列表

书源码: https://github.com/rust-lang/book/tree/master/src

discord: https://discord.com/invite/rust-lang

 

安装、文档相关命令

rustup update

rustup self uninstall

rustup doc

  

Hello World!


1. 用rustc

fn main() { //main.rs
    println!("Hello, world!");
}

 

rustc main.rs

 

2. 用cargo

cargo new hello_cargo
cargo build
cargo build --release
cargo run
cargo check #确保代码能通过编译,但是不编译

  

简单示例:Guessing Game

 

use rand::Rng;
use std::cmp::Ordering;//std::cmp下面的enum
use std::io;

fn main() {
    println!("Guess the number!");

    let secret_number = rand::thread_rng().gen_range(1, 101);

    loop {//infinite loop
        println!("Please input your guess.");//println! is a macro

        let mut guess = String::new();//let 定义变量,mut 决定变量是否可变,String是变长UTF8编码字符串

        io::stdin()
            .read_line(&mut guess)//mut 表示函数能够改变这个变量, &表示传递的是guess的引用,由于引用默认是immutatble,不可改变的,所以这里用&mut
            .expect("Failed to read line");//read_line返回的是io::Result,可能是Err或者Ok,res.expect在返回OK时获取OK内部包含的值,在返回Err的时候输出提示并crash,如果不expect,会编译时有Warning

        let guess: u32 = match guess.trim().parse() {//更改了guess的类型看,通过声明guess为u32,parse明确要转化为什么类型
            Ok(num) => num,
            Err(_) => continue,//注意这里match错误处理
        };

        println!("You guessed: {}", guess);

        match guess.cmp(&secret_number) {//match由多个arm组成
            Ordering::Less => println!("Too small!"),//Ordering::less是这个arm的pattern,如果被匹配上了,就运行后面的代码
            Ordering::Greater => println!("Too big!"),
            Ordering::Equal => {
                println!("You win!");
                break;
            }
        }
    }
}

 Cargo.toml中要加入依赖的crate:

[dependencies]
rand = "0.5.5"//实际上是^0.5.5,即任意和0.5.5版本的public API匹配的版本

 此时cargo是从registry(即crates.io的数据的拷贝中)获取的依赖包。生成的Cargo.lock文件确保了依赖包的版本不会因为重新build发生变化,除非手动upgrade(cargo update,获取新依赖包)。

变量

变量默认是immutable的,不能变更具体值,这样限制给程序带来了安全保障,有时不更改数据结构,而是直接新建或者拷贝一个类似的能够带来额外的安全保障。不过在变量声明时加上mut就能变成可写的变量。

rust同样支持const,那么immutable variable和const variable的差别是什么呢?

const MAX_POINTS: u32 = 100_000;

  

1.  显然,不需要在const上面使用mut,同时,普通变量的类型可以被某种程序上推测到,但是const是一定要声明类型的。

2. const变量可以在任何作用域声明,包括global scope。

3. const变量只能是一个不变的静态表达式计算的产物,而不能是一个函数调用或者必须要运行时才能确定的其他任何值。

使用const变量的好处-便于传达某个值的意义

Shadowing

变量Shadowing指用let声明一个新的、类型可能不同的变量替代一个旧的同样名字的变量。旧的is shadowed by新的。实际上,这两个变量除了名字相同,可以没有其他联系。这样做的好处是能够减少无意义的变量命名,比如a, a_str。

    let spaces = 123;
    let mut spaces = "   ";//That is ok!
    println!("Hello, world!");

 

数据类型

Rust是静态类型语言,需要能够在编译阶段确定所有变量的类型。Rust会尽量推断变量类型,如果无法推断,就会编译时报错。

let guess = "42".parse().expect("Not a number!");
  |         ^^^^^ consider giving `guess` a type

  

Scalar types

Integers, Floating-point, Booleans, Chararcters。

Integers: i8, i16, i32, i64, i128, u8, u16, u32, u64, u128, isize, usize  isize和usize与机器环境有关,如果是32位环境,长度32,64位环境长度64

输入方式: 0xff, 0o77, 0b11111_0000, b'A'

注意: Integer Overflow具有如下设置:当debug选项编译后,如果运行时出现Overflow会panic,但是在release下则会自动wrap(具体Wrap方法在Wrapping中实现)

Floating point: f32, f64

Char Type: 注意区分与u8的差别。此外,U+0000到U+D7FF到U+E000到U+10FFFF都能用char直接表示。Accented letters; Chinese, Japanese, and Korean characters; emoji; and zero-width spaces are all valid char values in Rust

 

组合类型-tuples and arrays

Tuple

fn main() {
    let tup: (i32, f64, u8) = (500, 6.4, 1);

    let (x, y, z) = tup;//destructuring
	
    let five_hundred = x.0;//访问tuple内元素

    let six_point_four = x.1;

    let one = x.2;
}

Array  

let a: [i32; 5] = [1, 2, 3, 4, 5];
let a = [3; 5];//[初始值;个数]
let first = a[0];

  

 函数

默认使用snake case方式(即使用小写和_)来写函数名和变量名。

fn main() {
    another_function(5, 6);
}

fn another_function(x: i32, y: i32) {
let y = {let x = 3;x + 1};//括号内是一个expression println!("The value of x is: {}", x); println!("The value of y is: {}", y);
5 //如果加一个分号,就变成了statement,就不能直接作为返回值,会报错 }

  

注释

基本的注释//

还有专用于文档生成的注释

 

控制流

If

fn main() {
    let condition = true;
    let number = if condition { 5 } else { 6 };

     if number % 4 == 0 {
        println!("number is divisible by 4");
    } else if number % 3 == 0 {
        println!("number is divisible by 3");
    } else {
        println!("number is not divisible by 4, 3, or 2");
    }
    println!("The value of number is: {}", number);
}

  

Loop

fn main() {
    let mut counter = 0;

    let result = loop {
        counter += 1;

        if counter == 10 {
            break counter * 2;//result = counter * 2, break语句返回了值
        }
    };

    loop {
        println!("again!");
    }
    println!("The result is {}", result);
}

  

While

fn main() {
    let a = [10, 20, 30, 40, 50];
    let mut index = 0;

    while index < 5 {
        println!("the value is: {}", a[index]);

        index += 1;
    }
	
	for element in a.iter() {//iteration
        println!("the value is: {}", element);
    }
    for number in (1..4).rev() {//rev: reverse the range
        println!("{}!", number);
    }
}

  

posted @ 2020-10-12 15:35  雪溯  阅读(134)  评论(0编辑  收藏  举报