Rust基础

Rust 是一个系统编程语言,它注重于三个方面:安全,速度和并发性。为了实现这些目标,它没有采用垃圾回收机制(GC)。


println!()这一行。这是一个 Rust ,是 Rust 元编程的关键所在。相反如果我们调用一个函数的话,它应该看起来像这样:println()(没有 !)。当看到符号 ! 的时候,就代表调用了一个宏而不是一个普通的函数。


Cargo

Cargo 是 Rust 的构建系统和包管理工具,同时 Rustacean 们使用 Cargo 来管理它们的 Rust 项目。Cargo 负责三个工作:构建你的代码,下载你代码依赖的库并编译这些库。

Cargo 编译你的程序所需要知道的三个配置:包的名字,版本,和作者。


语法

模式(Patterns)

在许多语言中,这叫做变量。不过 Rust 的变量绑定有一些不同的巧妙之处。例如let语句的左侧是一个“模式”,而不仅仅是一个变量。这意味着我们可以这样写:

let (x, y) = (1, 2);

在这个语句被计算后,x将会是1,而y将会是2。

可变性(Mutability)

绑定默认是不可变的(immutable)。下面的代码将不能编译:

let x = 5;
x = 10;
不止一个理由使得绑定默认不可变的,不过我们可以通过一个 Rust 的主要目标来理解它:安全。

初始化绑定(Initializing bindings)

Rust 变量绑定有另一个不同于其它语言的方面:绑定要求在可以使用它之前必须初始化。

作用域和隐藏(Scope and shadowing)

变量可以被隐藏。这意味着一个后声明的并位于同一作用域的相同名字的变量绑定将会覆盖前一个变量绑定。


表达式 VS 语句

表达式返回一个值,而语句不是。

x + 1;语句不返回一个值。会报错

fn add_one(x: i32) -> i32 {
    x + 1;
}

x + 1返回一个值。不会报错。

fn add_one(x: i32) -> i32 {
    x + 1
}


原生类型

切片

一个切片slice)是一个数组的引用(或者“视图”)。它有利于安全,有效的访问数组的一部分而不用进行拷贝。

在底层,slice 代表一个指向数据开始的指针和一个长度。

你可以用一个&[]的组合从多种数据类型创建一个切片。带有一个范围的[],允许你定义切片的长度:

let a = [0, 1, 2, 3, 4];
let complete = &a[..]; // A slice containing all of the elements in `a`.
let middle = &a[1..4]; // A slice of `a`: only the elements `1`, `2`, and `3`.

元组(Tuples)

元组(tuples)是固定大小的有序列表,元组是异质的:这个元组中有一个i32和一个&str。如下:

let x = (1, "hello");

这是一个长度为 2 的元组,由括号和逗号组成。下面也是同样的元组,不过注明了数据类型:

let x: (i32, &str) = (1, "hello");

你可以通过一个解构let(destructuring let)访问元组中的字段。下面是一个例子:

let (x, y, z) = (1, 2, 3);

println!("x is {}", x);

你也可以用索引语法访问一个元组的字段:

let tuple = (1, 2, 3);

let x = tuple.0;
let y = tuple.1;
let z = tuple.2;

println!("x is {}", x);

就像数组索引,它从0开始,不过也不像数组索引,它使用.,而不是[]

Vectors

相对数组长度可变。

必须用usize类型的值来索引:

let v = vec![1, 2, 3, 4, 5];

let i: usize = 0;
let j: i32 = 0;

// Works:
v[i];

// Doesn’t:
v[j];

注意:你不能在使用 vector 的所有权遍历之后再次遍历它。你可以使用它的引用多次遍历 vector。

例如,下面的代码不能编译。

let v = vec![1, 2, 3, 4, 5];

for i in v {
    println!("Take ownership of the vector and its element {}", i);
}

for i in v {
    println!("Take ownership of the vector and its element {}", i);
}

而如下代码则可以完美运行:

let v = vec![1, 2, 3, 4, 5];

for i in &v {
    println!("This is a reference to {}", i);
}

for i in &v {
    println!("This is a reference to {}", i);
}


所有权,有点类似c++的智能指针unique_ptr,引用和借用有点类似C++的引用概念,只有与引用(例如一个包含引用的struct)相关的变量才需要生命周期。


方法语句

Rust 通过 impl 关键字提供了使用 方法调用语法。

我们也可以定义一个不带self参数的关联函数。这是一个 Rust 代码中非常常见的模式:

struct Circle {
    x: f64,
    y: f64,
    radius: f64,
}

impl Circle {
    fn new(x: f64, y: f64, radius: f64) -> Circle {
        Circle {
            x: x,
            y: y,
            radius: radius,
        }
    }
}

fn main() {
    let c = Circle::new(0.0, 0.0, 2.0);
}

创建者模式(Builder Pattern)

我们说我们需要我们的用户可以创建圆,不过我们只允许他们设置他们关心的属性。否则,xy将是0.0,并且radius将是1.0。Rust 并没有方法重载,命名参数或者可变参数。我们利用创建者模式来代替。它看起像这样:

struct Circle {
    x: f64,
    y: f64,
    radius: f64,
}

impl Circle {
    fn area(&self) -> f64 {
        std::f64::consts::PI * (self.radius * self.radius)
    }
}

struct CircleBuilder {
    x: f64,
    y: f64,
    radius: f64,
}

impl CircleBuilder {
    fn new() -> CircleBuilder {
        CircleBuilder { x: 0.0, y: 0.0, radius: 1.0, }
    }

    fn x(&mut self, coordinate: f64) -> &mut CircleBuilder {
        self.x = coordinate;
        self
    }

    fn y(&mut self, coordinate: f64) -> &mut CircleBuilder {
        self.y = coordinate;
        self
    }

    fn radius(&mut self, radius: f64) -> &mut CircleBuilder {
        self.radius = radius;
        self
    }

    fn finalize(&self) -> Circle {
        Circle { x: self.x, y: self.y, radius: self.radius }
    }
}

fn main() {
    let c = CircleBuilder::new()
                .x(1.0)
                .y(2.0)
                .radius(2.0)
                .finalize();

    println!("area: {}", c.area());
    println!("x: {}", c.x);
    println!("y: {}", c.y);
}

trait 是一个告诉 Rust 编译器一个类型必须提供哪些功能语言特性,有点类似接口的概念。

由 Rust 标准库提供的特殊 trait,DropDrop trait 提供了一个当一个值离开作用域后运行一些代码的方法。例如:

struct HasDrop;

impl Drop for HasDrop {
    fn drop(&mut self) {
        println!("Dropping!");
    }
}

fn main() {
    let x = HasDrop;

    // Do stuff.

} // `x` goes out of scope here.

当在main()的末尾x离开作用域的时候,Drop的代码将会执行。Drop按照后进先出的顺序丢弃资源。



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值