文章目录
- 变量
- 可变与不可变变量
- 变量与常量
- 变量的Shadowing
- 标量类型
- 整数
- 复合类型
- 函数
- 控制流
- if else
- loop & while
- for in
- struct
- struct的定义
- Tuple Struct
- struct的方法与函数
变量
可变与不可变变量
Rust中使用let来声明变量,但是let声明的是不可变变量,如果想要可变,则需要加上mut关键字
fn main(){
let x = 10;
x = x + 1; //报错,因为x是不可变类型
let mut y = 11;
y = y + 1; //可行
}
变量与常量
常量与不可变变量一样都是不能被修改的,但是他与不可变变量有很多区别。
- 常量用const声明,且必须标注其类型
- 常量不能加mut修饰
- 常量可以在任何作用域内声明(包括全局)
- 常量只可以绑定在常量表达式中,无法绑定在函数的调用结果或者只能在运行时才能计算出的值。
- 在场许运行期间,长廊在其作用域内一直有效。
常量命名规范:全大写字母+下划线分割(不符合规范rust编译器会警告)
const MAX_POINT = 10000;
fn main(){
}
变量的Shadowing
Rust允许用户在一个作用域内重复的声明一个同名变量,并且可以是不同的类型的,而后声明的变量会覆盖前面声明的变量,这叫做变量的shadowing
fn main(){
let x = 100;
let x = "Test";
// 此时在对x进行操作,x的值就是"Test"
let number = "123123";
let number = number.trim().parse(); //转化为数字
//上述shadowing就使得通用一个number的变量名,但是却做到了类型转换。
}
标量类型
Rust是一个强类型的静态语言,这意味着在编译时编译器就需要明确的知道每个变量的类型,而不是像Py一样,“变量的类型是动态可变的”。
而上述的代码没有指定类型,只使用了let,是因为Rust的编译器可以自行推断出变量的类型(根据返回值,上下文,调用情况)。而有时情况过于复杂时便无法推断,便需要使用者自行标注出类型。
整数
整数类型如下:
可以看到分类无符号和有符号类型,并且每个类型都标清楚了占多少字节,最后一个isize类型表示的是CPU位数长度的整数类型(一个机器字长),与电脑硬件有关。
如下面代码所示,在变量后面加冒号在家类型就可以强制显示的的表明变量的类型。
fn main(){
let x: i8 = 18;
let y: u32 = 100;
}
整数字面值如上:
Rust允许在数字之间加下划线用于增加可读性。其中十六进制以0x开头,八进制以0o开头,二进制以0b开头。
而字节类型需要在字符串前加一个b。
Rust允许在数值后面加上类型来标注这个数字的类型
fn main(){
let x = 1002u32
let y = 10010010i32
let z = 0b100100
let a = 0xffa0
let b = b'B'
}
Rust的int默认值是32,浮点数默认值是64Bytes。如果整数类型发生了溢出,那么程序就会panic,如果在发布模式下编译则不会检查溢出。Rust的溢出会进行环绕操作,即对可取的最大值取余。
布尔类型则是有两个值,一个是true,一个是false占两个字节
fn main(){
let x: bool = true;
}
字符类型用来描述语言中最基础的单个字符,占四个字节,使用的值是Unicode表值。
fn main(){
let x: char = '你';
let u: char = '🙂';
}
复合类型
Rust提供了两种复合类型,一个是Tuple,一种是数组。
Tuple的创建遵循以下规则:
fn main(){
let x: (i32, char, f32) = (2003, 'a', 0.3);
println!("{} {} {}", x.0, x.1, x.2);
}
对于元组可以使用点+索引的形式来得到元素,元组是定长的,你可以认为它类似于C的struct的简化版。
元组还可以进行拆包,其过程如下:
fn main(){
let x: (i32, char, f32) = (2003, 'a', 0.3);
let (a, b, c ) = x;
}
另一个数据类型,数组则是定长,且使用[]来进行定义和创建
fn main(){
let x: [i32; 5] = [1, 2, 3, 4, 5]; // 创建一个i32类型,长度为5的数组
let y = [5; 4];// 创建4个i32类型值为5,长度为4的数组
let z = ["xxx", "yyy"]; //创建两个str类型的数组
}
上述需要注意的是let y = [5; 4];这种写法相当于是创建一个重复为5,长度为4的数组
函数
rust的函数的格式为:
fn 函数名(参数: 类型) -> 返回值{
函数体;
}
fn main(){
let x = test();
}
fn test(){
println!("Test");
}
上述的test的返回值是()。
fn main(){
let _x = test(32);
}
fn test(number: i32) -> (){
println!("Test number is {}", number);
}
Rust的函数体由Statement和Expression来构成,其中Statement指的是像let x = 10;这类的语句,而Expression则是x + 3, x == 5这样具有返回值的表达式。
Rust默认最后一个表达式即为返回值(或者函数题的值),如果没有则默认值为()
fn main(){
let x = test(10);
println!("Test number is {}", x);
}
fn test(number: i32) -> i32{
5 + number //注意,5 + number后面没有分号,否则将会被视为一个语句
}
这个函数体还可以作为变量的值来传递
fn main(){
let x = {
let mut _y = 11;
_y * 3
};
println!("{}", x)
}
上述x的的值是33,如果函数体最后一个语句没有返回值,则会得到()
控制流
与Rust控制流相关的有loop,while,for in的循环语句和if else,match的判断语句。其中match涉及到枚举不在这里记录,放在枚举那里。
if else
if和else就类似于C语言,当只有一个单独的语句时可以不用最外层的括号
fn main(){
let x = 10;
if x > 5 {
println!("大于5");
}else if x == 5 {
println!("小于5");
}else {
println!("小于5");
}
}
三元运算符,有点类似于python与C的结合体,例子如下
if 条件 {结果1} else {结果2}
fn main(){
let x = if 5 > 3 {5} else {3};
println!("x is {}", x);
let y = if x != 5 {
x * 2
}else{
x - 3
};
println!("y is {}", y);
}
/*
Compiling hello_world v0.1.0 (E:\RustProject\Hello_World)
Finished dev [unoptimized + debuginfo] target(s) in 0.69s
Running `target\debug\hello_world.exe`
x is 5
y is 2
*/
loop & while
loop的用法就是相当于while true,也就是loop内的语句会被不停地循环,直到遇到break为止。
用法如下:
fn main(){
let mut x = 0;
loop{
x += 1;
if x > 10{
break;
}
}
println!("x is {}", x);
}
而对于while循环则是和C和Py一样,break和continue语句也是同样的道理。
while 条件{}
fn main(){
let mut x = 0;
while x <= 10 {
x += 1;
}
println!("x is {}", x);
}
for in
for in则是类似于py的for in集合的模式,in后面需要跟一个可以迭代的类型例如数组。
需要注意的是此时tmp是&i32类型,也就是说它的类型是确定的,没法for in一个多种类型的Tuple。
fn main(){
let x = [3, 4, 5, 6];
for tmp in x.iter(){ //iter方法得到x的迭代器
println!("{}", tmp);
}
}
/*
Compiling hello_world v0.1.0 (E:\RustProject\Hello_World)
Finished dev [unoptimized + debuginfo] target(s) in 1.07s
Running `target\debug\hello_world.exe`
3
4
5
6
*/
对于计数之类的需求,Rust提供了Range的方法,可以使用a…b来构造一个a+1,a+2…, b-2, b-1的序列来进行遍历,如下:
fn main(){
for x in 3..10{
println!("{}", x);
}
}
/*
Compiling hello_world v0.1.0 (E:\RustProject\Hello_World)
Finished dev [unoptimized + debuginfo] target(s) in 1.03s
Running `target\debug\hello_world.exe`
3
4
5
6
7
8
9
*/
struct
struct的定义
Rust的struct定义如下:
struct 名称{
变量1: 类型,
变量2: 类型…
}
struct Rectangle{
width: u32,
length: u32
}
而struct的初始化则是使用名字+变量名:值的形式初始化,注意,struct不允许有字段为空值,也就是说需要全部值都初始化
let re = Rectangle{
width: 10,
length: 19
};
而这些值的访问就类似于C的struct,直接用点+对应的字段即可。
struct也可以设置为mut,而对于struct来说,一旦设置为mut,则里面每个值都必须要是mut,也就是说都是可变的。
let mut re = Rectangle{
width: 10,
length: 19
};
re.width = 100;
当有变量名与struct内部定义的变量名同名时,可以省去冒号进行初始化
struct Rectangle{
width: u32,
length: u32
}
fn main(){
let width = 9;
let mut re = Rectangle{
width, // 省去了冒号,因为width同名
length: 19
};
}
当想要对struct进行更新时,有一种简单的简写操作,如下:
let width = 9;
let mut re = Rectangle{
width,
length: 19
};
let re2 = Rectangle{
width: 100,
..re //re表示,剩下的字段的值与re的剩余字段的值相同
};
Tuple Struct
struct的方法与函数
对于一个struct,它拥有对应的方法和函数,而对于方法则是应用于struct的上下文中的,可以获取和修改具体的struct的值。而函数则不能,他只是与某种struct关联到了一起而已。
使用impel关键字来为struct绑定方法和函数。
第一个参数带有self关键字就是方法,而不带有则是函数
struct Rectancle{
width: u32,
length: u32,
}
impl Rectancle {//为Rectangle绑定函数和方法
fn area(&self) -> u32{//绑定一个方法&self表示Rectangle结构体本身
self.width * self.length //返回面积
}
}
fn main(){
let y = Rectancle{
width: 10,
length: 15
};
println!("Area is {}", y.area());
}
下面是绑定一个函数例子
struct Rectancle{
width: u32,
length: u32,
}
impl Rectancle {
fn area(&self) -> u32{
self.width * self.length
}
fn make_square(size: u32) -> Rectancle { //构造一个正方形
Rectancle { width: (size), length: (size) }
}
}
fn main(){
let sq = Rectancle:: make_square(10);//通过使用::的方式来调用函数
println!("Area is {}", sq.area());
}
需要注意,每个struct允许拥有多个impel的模块。