Please enable Javascript to view the contents

写给javascript程序员的rust教程(二)变量与数据类型【译】

 ·  ☕ 5 分钟

原文:Rust for JavaScript Developers - Variables and Data Types

翻译:http://www.mzh.ren/

这是写给javascript程序员的rust教程系列文章的第二部分:变量与数据类型。

第一部分见:写给javascript程序员的rust教程(一)工具链概述【译】 – 码中人

变量

JavaScript有三种声明变量的方法:var,const和let。Rust也有const和let,但与JavaScript相比,它们的工作方式截然不同。

let

在rust中,用let 声明 变量:

1
let a = 123;

正如预期的那样,这将为变量 a 分配 123 的值。但默认情况下 ,Rust 变量不可更改,也就是说在赋值之后,你将无法改变它的值。

1
2
let a = 123;
a = 456; // Error! :(

乍一看,这与JavaScript的const类似,但JavaScript的const并不能使变量不可变,它只是使绑定不可变。

如果你想让变量可变,你需要使用mut关键字显式地声明。

1
2
let mut a = 123;
a = 456; // No Error :)

const

Rust的const与JavaScript的const也有很大的不同–最好把Rust的const看成是一个常量值的 “标签”。在编译时,它们在所有被使用的地方都会被它们的实际值取代。它通常用于端口号、超时值、错误代码等常量。

你也可以在全局级别定义const外部函数,这是用let做不到的。


数据类型

数值

在JavaScript中,我们同时具有数字类型(整数(无小数点的数字)和浮点数(有小数点的数字))。

在Rust中,整数和浮点数有很多选择,但默认情况下,我们可以将i32用作整数,将f64用作浮点数。

1
2
let x = 123; // i32
let y = 4.5; // f64

布尔值

非常简单-JavaScript和Rust都具有带有true / false值的布尔值。

1
let x = false; // bool

字符串

在使用JavaScript时,我们通常不会过多考虑字符串-它们总是可以“正常工作”。在Rust中,字符串的类型有很多种,其中被广泛使用的字符串是:String和&str。

String是可变长的,&str 是定长的。

当你使用字符串字面量创建字符串,该字符串默认为&str类型。

1
let name = "Saitama"; // &str

可以使用String::from 或 t0_string 方法创建String 类型字符串。

1
2
let name  = String::from("Genos"); // String
let name2 = "King".to_string();    // String

通过 as_str 函数可以将 String 类型转化成 &str 类型。

1
2
let name2 = "King".to_string(); // String
let name3 = name2.as_str();     // &str

关于字符串,后续文章会进一步讨论。


Optionals

JavaScript的空值有两种类型–undefined和null。undefined是指变量、属性等未被定义,而null则是指故意为空。

Rust 完全没有这些–它甚至没有一个专门的 null 数据类型。与之替代,它有一个叫做Option的东西。当我们遇到一个值可能为空或初始未定义的情况时,就会使用这个 Option 类型。

使用过TypeScript/Flow的人可能会发现这里有一些相似之处,但在如何创建和使用optionals方面却有很大不同。

假设我们想写一个函数,接收一个文件路径并返回其内容。并且要求当空字符串作为文件路径传递时,我们想返回一个 “null “值。

下面是我们在JavaScript/TypeScript中的写法:

1
2
3
4
5
6
7
8
9
function read_file(path: string): string | null {
  const contents = "hello";

  if (path !== "") {
    return contents;
  }

  return null;
}

Rust 通过 Option 完成相同的操作:

1
2
3
4
5
6
7
8
9
fn read_file(path: &str) -> Option<&str> {
  let contents = "hello";

  if path != "" {
    return Some(contents);
  }

  return None;
}

你可以看到,对于空值,我们返回None,但对于非空值,我们并没有原封不动地返回内容,而是将其 “包裹 “在Some里面并返回。返回类型也不是TypeScript例子中的 “string或null”,而是 “Option that contains &str “类型。

下面是你在JavaScript/TypeScript中调用read_file这个函数的方式:

1
2
3
4
5
6
7
8
9
function main() {
  const file_contents = read_file("/path/to/file");

  if (file_contents !== null) {
    console.log(file_contents); // file_contents is refined to string type
  } else {
    console.log("Empty!");
  }
}

Rust 调用方式:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
fn main() {
  let file = read_file("path/to/file");

  if file.is_some() {
    let contents = file.unwrap();
    println!("{}", contents);
  } else {
    println!("Empty!");
  }
}

如你所见,我们需要手动 “拆开 “Option来获取里面的内容。


数组

与字符串类似,Rust有两种类型的数组–一种是固定大小的数组(简称为 “Array”),另一种是可以增长/收缩大小的数组(称为 “Vectors”)。

Arrays

1
2
3
4
fn main() {
  let list = [1, 2, 3];
  println!("{:?}", list);
}

Vectors

1
2
3
4
5
fn main() {
  let mut list = vec![1, 2, 3];
  list.push(4);
  println!("{:?}", list);
}

对象

从技术上讲,所有的非原生类型在JavaScript中都是 “对象”,但我们通常使用 “对象 “一词来做两件事–Bag of data (数据包) 和hashmap(hash字典)。

Bag of data (数据包)

与其他语言不同的是,JavaScript最酷的地方,你不需要经过很多仪式来创建一个对象。比如,要在JavaScript中创建一个雇员对象:

1
2
3
4
5
6
7
function main() {
  const employee = {
    name: "Saitama",
    age: 25,
    occupation: "Hero",
  };
}

Rust创建类似javascript的对象,需要用到struct:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
struct Employee {
  name: String,
  age: i32,
  occupation: String,
}

fn main() {
  let employee = Employee {
    name: "Saitama".to_string(),
    age: 25,
    occupation: "Hero".to_string(),
  };
}

HashMap

在JavaScript中,要创建具有任意键值对的对象,我们可以使用对象字面量或Map对象:

1
2
3
4
5
6
7
8
function main() {
  const colors = new Map();

  colors.set("white", "#fff");
  colors.set("black", "#000");

  console.log(colors.get("white")); // #fff
}

Rust 可以使用HashMap类型实现:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
use std::collections::HashMap;

fn main() {
  let mut colors = HashMap::new();

  colors.insert("white".to_string(), "#fff");
  colors.insert("black".to_string(), "#000");

  println!("{:?}", colors.get("white").unwrap()); // #fff
}

请注意上面 unwrap 的用法。HashMap的get方法返回的是一个Option类型,我们需要对这个Option类型进行解包来获取里面的值。

谢谢你的阅读 :)

分享

码中人
作者
码中人
Web Developer