RUST初试
学习RUST是因为前段时间在尝试OAM(Open Application Model) Rudr这个实现,发现是用RUST语言写的,看不懂……。 所以索性学习一下。
学习了一个星期,感觉比当时学习golang更是难以适应。golang其实很多还是类C的语法,只不过变量类型挪到变量名之后;多了channel,goroutine,interface,GC一些;用过之后感觉golang还是很不错。
但是学习RUST的基本语法之后,让我感觉之前习惯的一些东西都要被改观了,它的编译器要做的得多么强大,才能hold住各种情况:ownership,mutable,immutable……你需要了解什么时候你的变量就不能用了。
为了理清楚,还是把一些重点记录下来;目前处于表层阶段,后期会对底层实现进行更深入的了解和学习。
RUST的变量,默认immutable
RUST中定义的变量(使用let关键字来声明,和javascript类似)默认是Immutable的。 这个是我使用过的语言中第一个这样设计的,让人很不理解;其实我觉得在程序中,当我们声明变量的时候,大多数时候是需要对它进行更改的,为什么默认不是mutable的呢? 在C语言中,如果希望一个变量不被修改,那就用const来修饰。
RUST的变量注意点:
1.默认是immutable的,不能对同一个immutable变量赋值2次;但是你可以对同一个名字的变量声明多次,比如let x=1; let x=2; let x=3;(官网说这种叫做shadowing)
2. 可以使用mut关键字来让变量成为mutable,例如 let mut x=5;x=6;
3. RUST中也有const的关键字,这个仅仅是用来声明常量用的;
RUST是statically typed 语言
RUST的变量类型需要在编译阶段就需要知道类型了,无论是通过显示还是隐示。
显示地类型定义是 let var_name: var_type = value;
(这里的语法注意的是需要一个冒号:隔开变量名和变量类型)
基本类型:
- char
- bool: true / false
- 浮点类型 f32, f64
- 有符号整数类型: i8,i16,i32, i64, i128, isize (根据系统run在多少为的机器上决定)
- 无符号整数类型: u8, u16, u32, u64, u128, usize
tuple type:
我们可以把几种类型bundle在一起定义一个tuple类型,但是和struct类型又不同,看一下使用的例子
let tup: (i32, f64, u8) = (500, 6.4, 1);
let (x, y, z) = tup;
let x = tup.0;
let y = tup.1;
let z = tup.2;
数组类型:
let a = [1,2,3];
let b: [i32; 3] = [1, 2, 3]; //i32是数组的类型; 3表示数组的大小
有时候需要初始化一个数组,可以用下面的方面:
let a = [0:5]; //这个数组的大小是5,所有element初始化为0
访问数组的element和其他语言一样:
let x = a[0];
enum类型
RUST中简单的Enum和C语言类似
enum IpType {
IPV4,
IPV6,
}
在C语言中,我们往往需要定义一个struct,一个field表示类型,另一个表示address的value;但是在RUST中可以省去一个struct的定义,同时在RUST中实现:
enum IpType {
IPV4(String),
IPV6(String),
}
let home = IpType::IPV4(String::from("127.0.0.1"));
let loopback = IpType::IPV6(String::from("::1"));
Enum同时也可以类似struct,实现自己的Methods
Struct类型
- Struct的语法和C语言类似:
struct Fruit {
color: String,
shape: String,
}
fn main() {
let apple = Fruit{
color :String::from("red"),
shape: String::from("round"),
};
apple.color = String::from("green");
}
如果从其他结构体变量复制部分fields,可以用…
//The syntax .. specifies that the remaining fields not explicitly set should have the same value as the fields in the given instance. 从apple这个结构体复制shape这个field
let organge = Fruit{
color : String::from("orange"),
..apple
};
- 有几个struct的变种:
- tuple struct: 只定义类型,没有field的name,比如
struct Color(i32, i32, i32);
let black = Color(0,0,0);
- unit-like struct: 在golang里面也有空的struct{}使用, 这种结构体不占用空间:我们可以用这种空结构体 来仅仅实现某些方法; 或者make(chan struct{}),这个chan不写入数据,可以通过close()来进行关闭操作。
RUST中的unit-like struct 也是没有任何fields的
- 打印struct
#[derive(Debug)] 和{:?}
#[derive(Debug)]
struct Test{
//struct definition,
}
let var = Test{....};
println!("rect1 is {:?}", var);
- Struct的Methods
类似golang中interface可以实现Methods,RUST中的struct也有自己的methods。语法比较奇怪:
以下列子摘自https://doc.rust-lang.org/book/ch05-03-method-syntax.html
#[derive(Debug)]
struct Rectangle {
width: u32,
height: u32,
}
impl Rectangle {
fn area(&self) -> u32 {
self.width * self.height
}
}
带有&self参数的是struct的methods,在访问的时候用. 就可以了;
不带&self参数的是associated functions, 一般用于构造函数,访问这种方法时用::
RUST的function定义
fn function_name(param_name1: param_type1, param_name2: param_type2) -> return_type {
}
例如:
let test(x: i32, y: i32) {
}
RUST 和其他语言不同之处表现在,它有Statement和Expressions的区别,先看一下定义:
- Statements are instructions that perform some action and do not return a value.
- Expressions evaluate to a resulting value
为了简单记忆,凡是带有分号;结尾的语句就是Statements,他们是没有返回值的;凡是没有带分号的语句是Expressions,是带有返回value的。
当第一次看到function return value的语句感觉特别奇怪:
fn return_value() -> i32 {
let x=5; //这个表示statement,这个语句没有返回值,从而也不能像C语言那样连续赋值,比如int i=j=0; 如果你写成 let x=(let y=5);是会报错的
x+1; //这个语句也是statement
5 //这个句子是expression,表示函数返回5
}
Flow-control 语法
flow-control的语法和其他类似:
- if/else if/ else : 条件语句不需要用()包住,和golang类似; 判断的内容必须是bool类型,这点和C语言不同
- 替代C语言中的三元运算符: let number = if condition { 5 } else { 6 };
- for:用于遍历collections
比如:for element in a.iter() {} //a is an array
for number in (1…4).rev() {) - while:根据条件判断来循环
- loop: 无限循环知道显示地break
loop {
//some condition meet, break the loop. We can also break with a value
break
//or
break some_value
}