写点什么

5 分钟速读之 Rust 权威指南(三)

用户头像
码生笔谈
关注
发布于: 2021 年 05 月 17 日
5分钟速读之Rust权威指南(三)

变量与函数

变量

变量的值默认是不可变,是不是有点诧异?叫变量却不可变:


let x = 5;println!("{}", x); // 5x = 6; // 报错,x是不可变的
复制代码


使用 mut 关键字来让变量可变:


let mut y = 5;println!("{}", y); // 5y = 6; // 加了mut之后就可以改变了println!("{}", y); // 6
复制代码


变量允许重复定义,将上一次的定义覆盖:


let z = 5;println!("{}", z); // 5let z = 6; // 重复定义println!("{}", z); // 6
// 允许改变上次的类型let spaces = "123";let spaces = spaces.len(); // 从&str变成usizeprintln!("{}", spaces); // 3
// 使用mut只能变变量值,不能改变类型let mut spaces2 = "123";spaces2 = spaces2.len() // 报错,预期一个&str,却得到一个usize
复制代码


常量使用 const 关键字来定义,名称全部大写,并显式标明数据类型:


const YEAR: u32 = 365;println!("{}", YEAR); // 365
复制代码

使用解构定义变量

从数组中解构成员:


let arr = [1, 2, 3];let [a, b, c] = arr;println!("{}-{}-{}", a, b, c); // 1-2-3
// 只解构部分成员将报错let [a,b] = arr; // 报错,预期解构3个成员
// 使用..来省略不需要的成员let [a, b, ..] = arr;
复制代码


从元组中解构成员:


let tuple = (1, "2", 3.5);let (a, b, c) = tuple;println!("{}-{}-{}", a, b, c);
// 元组中也必须结构全部成员let (a, b) = tuple; // 报错,预期解构3个成员
// 使用..来省略不需要的成员let (a, b, ..) = tuple;
复制代码


从结构体中解构属性,可以先将结构体理解成 JS 中的对象:


// 声明一个User类型的结构体struct User {  name: String,  age: u8,}
// 定义一个xiao_ming变量,是User结构体类型let xiao_ming = User { name: "xiaoming".to_string(), age: 18};
// 全部解构let User { name, age } = xiao_ming;println!("name:{} age:{}", name, age); // name:xiaoming age:18
// 解构部分,仍需要保证左模式与有结构相符合let User { age } = xiao_ming; // 报错,左边的模式与右边的结构不匹配,缺少age
// 使用..来省略不需要的成员let User { age, .. } = xiao_ming;println!("age:{}", age); // 18
复制代码


从枚举中结构成员,可以先简单认识下枚举,后面会有章节介绍:


// 定义一个枚举类型:Ipenum Ip {  // 包含一个String类型的“变体”:V4  V4(String)}
// 定义一个Ip::V4类型的变量(双冒号可以理解为“.”),包含的值是"127.0.0.1"let localhost = Ip::V4(String::from("127.0.0.1"));
// 当枚举只有一个类型的时候我们可以直接进行解构,let后面是模式,括号中的ip是解构出来的变量let Ip::V4(ip) = localhost;println!("{}", ip); // 127.0.0.1
// 当枚举有多个类型时直接解构将报错enum Ip { V4(String), V6(String)}let Ip::V4(ip) = localhost; // 报错, 因为localhost有可能是V6类型的
// 使用if let来对多个类型进行覆盖if let Ip::V4(ip) = localhost { println!("V4: {}", ip); // 127.0.0.1 } else if let Ip::V6(ip) = localhost { println!("V6: {}", ip);} else { println!("other");}
复制代码

函数

函数使用关键字 fn 来定义,命名使用 snake case 命名方式,用下划线分割单词名称:


fn fn_name() {  println!("fn_name called");}
复制代码


调用函数:


foo();
复制代码


函数参数在技术文档中有两种区分:parameter 表示形参,argument 表示实参,但是我们一般不会区分,函数参数的类型必须显式注明:


foo(100); // 函数是允许调用在定义之前的fn foo(num: i32) {  println!("foo called with: {}", num); // foo called with: 100}
复制代码


函数的返回值的类型也需要显式注明,使用→来标注返回值类型:


// 标明返回i32类型fn add_one(num: i32) -> i32  {  return num + 1}
// return关键字可以省略fn add_two(num: i32) -> i32 { // 由于num+1后没有其他的调用,则会被为是函数的返回值 // 但是末尾不能加分号结尾 num + 2}
复制代码


函数的返回值其实是元组:


// 相当于返回了空元组:()fn foo() {}
// 相当于返回了具有一个成员的元组:(1)fn foo2() -> i32 { return 1}let num = foo2();println!("{}", num); // 1
// 所以可以返回多个成员的元组fn foo4() -> (i32, bool) { return (1, true)}let res = foo4();// 打印元组或者数组需要使用:?占位符println!("{:?}", res); // (1, true)
// 可以解构返回值let (num, boo) = foo4();println!("{}-{}", num, boo); // 1, true
// 解构返回值仍然需要解构所有成员let (num) = foo4(); // 报错,返回值的元祖中包含两个成员
// 使用..来省略不需要的成员let (num, ..) = foo4();
// 由于返回值是一个元组,所以用“.”可以取返回值的成员let tup = foo4()println!("{}", tup.0); // 1println!("{}", tup.1); // true
复制代码

函数体中的语句和表达式

语句指那些执行操作但没有返回值的指令:


// 使用let关键字创建变量并绑定值时使用的指令是一条语句let x = 2;
// let z = 5是语句,没有返回值,所以rust不允许这样做let y = (let z = 5); // 报错
复制代码


表达式则是指会进行计算并产生一个值作为结果的指令:


// 数学运算是表达式1 + 2
// 作用域块也是表达式let x = { let y = 1; // 假如在表达式的末尾加上了分号,就变为了语句而不会返回任何值 y + 2};println!("{}", x) // 3
复制代码


发布于: 2021 年 05 月 17 日阅读数: 14
用户头像

码生笔谈

关注

欢迎关注「码生笔谈」公众号 2018.09.09 加入

前端、Rust干货分享,一起成为更好的Javascripter & Rustacean

评论

发布
暂无评论
5分钟速读之Rust权威指南(三)