rust(三)-通用的编程概念

180 阅读7分钟

1、变量与可变性

全用let关键字来声音变量,一般浏览器会给他推断为i32类型,一般默认为不可变,如果需要声明变量,需要加mint关键字声明。

  • 变量和常量
    • 常量(constant), 常量在绑定值以后也是不可变的,但是它与不可变的变量有很多区别:
      • 不可以使用mut, 常量永远都是不可变的
      • 声明常量使用const关键字,它的类型必须被标注
      • 常量可以在任何作用域进行声明,包括合局作用域
      • 常量只可以绑定到常量表达式,无法绑定到函数的调用结果或只能在运行时才能计算出的值
    • 在程序序运行期间,常量在其声明的作用域内一直有效
    • 命名规范: Rust 里常用使用全大写字母,每个单词之间用下划线分开,例如:MAX_POINITS
    • 例子: const MAX_POINTS:u32 = 100_000
  • shadowing
    • 可以使用相同的名字声明新的变量,新的变量就会shadow(隐藏)之前声明的同名变量
      • 在后续的代码中这个变量名代表的就是新的变量
    let x= 5;
    let x = x+1;
    let x = x *2;
    
    • shadow 与 mut关键字声音的区别
      • 如果不使用let关键字,那么重新给mut的变量赋值会导致编译时错误
      • 而使用let声明的同名新变量,也是不可变的
      • 使用let声明的同名新变量,它的类型可以与之前不同

2、数据类型

  • 标量和复合类型
  • Rust 是静态编译语言, 在编译时必须知道所有变量的类型
    • 基于使用的值,编译器通常能够推断它的具体类型
    • 但如果可能的类型比较多(例如把string转为整数的parse方法),就必须添加类型的标注,否则编译会报错。
    et guess: u32 = "42".parse().expect("Not a number!");
    

标量类型

整数类型

  • 整数类型没有小数部分
  • 例如 u32 就是一个无符号的整数和类型,占据 32们的空间
  • 无符号整数类型以U开头
  • 有符号整数类型以i开头
  • isize和usize类型的位数由程序运行的计算机的架构所决定
  • 使用isize或usize的主要场景是对某种集种集合进行索引操作
  • 整数字面值
  • 除了byte类型外,所有的数值字面值都允许使用类型后缀 例如:57u8
  • 如果你不太清楚应该使用哪种类型,可以使用rust相应的默认类型
  • 整数的默认类型就是i32
    • 总体上来说速度很快,即使在64位系统中

整数溢出

  • 调试模式下编译:Rust 会检查整数溢出,如果发生溢出,程序在运行时会panic
  • 发布模式下(--release)编译:rust不会检查可能有导致panic的整数溢出
    • 如果溢出发生:rust会执行“环绕操作”

浮点类型

  • rust 有两种基础的浮点类型
    • f32 32位 单精度类型
    • f64 64位 双精度
  • rust的浮hokodga全用了ieee-754标准来表述
  • f64是默认类型,因为在现代cpu上f64和f32的速度差不多,而且精度更高

布尔类型

  • 关键字 bool
  • 两个值 true 和 false
  • 占一个字节

字符类型

  • rust 语言中char类型被用来描述语言中最基础的单个字符
  • 字符类型的字面值使用单引号
  • 占用4字节大小
  • 是unicode 标量值, 可以表示仳ascll多得多的字符内容:拼音、中日韩文、零长度空白字符、emoji表情等。
    • U+0000 ~ U+D7DD
    • U+E000 ~ U+10FFFF
  • 但unicode中并没有“字符”的概念,所以直觉上认为的字符也许与rust中的概念并不相符

复合类型

  • 复合类型可以将多个值放在一个类型里
  • rust提供了两种基础的复合类型:元组(tuple)、数组

元组(tuple)

  • tuple长度是固定,一旦声明不能修改
  • 获取tuple的元素值
    • 可以使用模式匹配来解构(destructure)一个tuple来获取元素的值
    fn main() {
      let tup = (500, 6.4, 1);
    
      let (x, y, z) = tup;
    
      println!("The value of y is: {}", y);
    }
    
    • 可以使用点标记法
      fn main() {
      let x: (i32, f64, u8) = (500, 6.4, 1);
      
      let five_hundred = x.0;
      
      let six_point_four = x.1;
      
      let one = x.2;
      }
      

数组的用处

  • 如果想让你的数据存入在stack上而不是heap上,或者想保证有固定数量的元素,这时使用数组更有好处。
  • 数组没有vector灵活
    • vector和数组类似,它由标准库提供
    • vector 的长度可以改变
    • 如果你不确定当前的场景是用数组还是vector,那么估计你应该用 vector

数组的类型

  • 数组的类型以这种形式表示

#![allow(unused)]
fn main() {
let a: [i32; 5] = [1, 2, 3, 4, 5];
}
  • 另外一种声明数组的方法
    • 在中括号里指定初始值
    • 然后是一个;
    • 然后是数组的长度

#![allow(unused)]
fn main() {
let a = [3; 5];
}
  • 访问数组的元素
fn main() {
   let a = [1, 2, 3, 4, 5];

   let first = a[0];
   let second = a[1];
}
  • 数组是stack上分配的单个块的内存
  • 可以使用索引来访问数组的元素(例子)
  • 如果访问的索引超出了数组的范围, 那么:
    • 编译会通过
    • 运行时会报错 (runtime时会panic)
      • rust不会允许其继续访问相应该地址的内存

函数

  • 声音函数使用fun关键字
  • 依照惯例,针对函数和变量名,Rust使用snake case 命名规范:
    • 所有的字母都是小写的,单词之间使用下划线分开
  • 函数的参数
    • parameters, arguments
    • 必须指明每个参数类型,可以有多个
  • 函数体中的语句和表达式
    • 函数体由一系列语句组成,可选的由一个表达式结束
    • Rust 是一个基于表达式的语言
    • 语句是执行一些动作的指令
    • 表达式会计算产生一个值
    • 函数的定义也是语句
    • 语句不返回值,所以不可以使用let将一个语句赋给一个变量
  • 函数的返回值
    • 在 -> 符号后边声明函数返回值的类型, 但是不可以为返回值命名
    • 在 Rust 里面,返回值就是函数体里面最后一个表达式的值
    • 若想提前返回,需使用 return 关键字, 并指定一个值
      • 大多数函数都是默认使用最后一个表达式作为返回值
  • 注释
    • 单行注释
    • 多行注释
    • 文档注释

控制流

  • if表达式允许你根据条件来执行不同的代码分支
    • 这人条件必须是bool类型
  • if 表达式中,与条件相关联的代码块叫做分支(arm)
  • 可选的,在后边可以另一个else表达式
fn main() {
    let number = 3;

    if number < 5 {
        println!("condition was true");
    } else {
        println!("condition was false");
    }
}

Rust的循环

Rust提供了3种循环:loop,while,for

loop

loop关键字告诉rust反复的执行一块代码,直到你喊停

fn main() {
    let mut counter = 0;

    let result = loop {
        counter += 1;

        if counter == 10 {
            break counter * 2;
        }
    };

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

while 条件循环

fn main() {
    let mut number = 3;

    while number != 0 {
        println!("{}!", number);

        number -= 1;
    }

    println!("LIFTOFF!!!");
}

for循环

  • 可以使用while或loop来遍历集合,但是易错且低效
  • 使用for循环更简洁紧凑,它可以针对集合中的每个元素来执行一些代码
fn main() {
    let a = [10, 20, 30, 40, 50];

    for element in a {
        println!("the value is: {}", element);
    }
}

  • 由于for循环的安全、简洁性,所以它在rust里用的最多
  • Range
    • 标准库提供
    • 指定一个开始数字和一个结束数字, range可以生成它们之间的数字(不含结束)
    • rev 可以反转

参考链接:doc.rust-lang.org/book/ch03-0…