rust 语法示例

official Learn Rust

basic concept

trait

variables

by default variables are immutable

let vairable:i32 = 100;

pattern destructure

模式解构声明

Shadowing

变量遮蔽

fn main() {
let x = 5;

let x = x + 1;

let x = x * 2;

println!("The value of x is: {}", x);
}

mutable

following is mutable code use mut indicate

let mut x = 5;
println!("The value of x is: {}", x);
x = 6;
println!("The value of x is: {}", x);

difference with constant

  • Not allowed use mut with constants
  • Declare constants with const keyword, and the type of the value must be annotated
  • Constants can be declared in any scope
  • The last difference is that constants may be set only to a constant expression, not the result of a function call or any other value that could only be computed at runtime.

raw identifiers

Sometimes, you may need to use a name that’s a keyword for another purpose. Maybe you need to call a function named match that is coming from a C library, where ‘match’ is not a keyword. To do this, you can use a “raw identifier.” Raw identifiers start with r#:

let r#fn = "this variable is named 'fn' even though that's a keyword";

// call a function named 'match'
r#match();

Data Types

Scalar Types

A scalar type represents a single value.

Rust has four primary scalar types: integers, floating-point numbers, Booleans, and characters

integers

Length Signed Unsigned
8-bit i8 u8
16-bit i16 u16
32-bit i32 u32
64-bit i64 u64
128-bit i128 u128
arch isize usize

Additionally, the isize and usize types depend on the kind of computer your program is running on: 64 bits if you’re on a 64-bit architecture and 32 bits if you’re on a 32-bit architecture.

Number literals Example
Decimal 98_222
Hex 0xff
Octal 0o77
Binary 0b1111_0000
Byte (u8 only) b’A’

floating-point numbers

fn main() {
let x = 2.0; // f64

let y: f32 = 3.0; // f32
}

boolean

true or false that’s a question

characters

Rust’s char type represents a Unicode Scalar Value, which means it can represent a lot more than just ASCII.
Accented letters; Chinese, Japanese, and Korean characters; emoji; and zero-width spaces are all valid char values in Rust. Unicode Scalar Values range from U+0000 to U+D7FF and U+E000 to U+10FFFF inclusive.

fn main() {
let c = 'z';
let z = 'ℤ';
let heart_eyed_cat = '😻';
}

compound types

Compound types can group multiple values into one type. Rust has two primitive compound types: tuples and arrays.

Tuples

A tuple is a general way of grouping together some number of other values with a variety of types into one compound type. Tuples have a fixed length: once declared, they cannot grow or shrink in size.

fn main() {
let tup: (i32, f64, u8) = (500, 6.4, 1);
}

access data

fn main() {
let tup = (500, 6.4, 1);

let (x, y, z) = tup;

println!("The value of y is: {}", y);
}
fn main() {
let x: (i32, f64, u8) = (500, 6.4, 1);

let five_hundred = x.0;

let six_point_four = x.1;

let one = x.2;
}

Array Type

arrays in Rust have a fixed length, like tuples.
Arrays are useful when you want your data allocated on the stack rather than the heap

fn main() {
let a = [1, 2, 3, 4, 5];
}

Arrays have an interesting type; it looks like this: [type; number]. For example:

#![allow(unused_variables)]
fn main() {
let a: [i32; 5] = [1, 2, 3, 4, 5];
}

invalide element access

fn main() {
let a = [1, 2, 3, 4, 5];
let index = 10;

let element = a[index];

println!("The value of element is: {}", element);
}

The compilation didn’t produce any errors, but the program resulted in a runtime error and didn’t exit successfully. When you attempt to access an element using indexing, Rust will check that the index you’ve specified is less than the array length. If the index is greater than the length, Rust will panic.

functions

Rust code uses snake case as the conventional style for function and variable names.

fn main() {
another_function(5, 6);
}

fn another_function(x: i32, y: i32) {
println!("The value of x is: {}", x);
println!("The value of y is: {}", y);
}

return value use ->

fn main() {
let x = plus_one(5);

println!("The value of x is: {}", x);
}

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

comments

same to c language.

// one line comment
/*
block Comments
block Comments
*/

Doc comments which are parsed into HTML library


control flow

if

fn main() {
let number = 3;

if number < 5 {
println!("condition was true");
} else {
println!("condition was false");
}
}

fn main() {
let number = 6;

if number % 4 == 0 {
println!("number is divisible by 4");
} else if number % 3 == 0 {
println!("number is divisible by 3");
} else if number % 2 == 0 {
println!("number is divisible by 2");
} else {
println!("number is not divisible by 4, 3, or 2");
}
}

using with let
Because if is an expression, we can use it on the right side of a let statement

fn main() {
let condition = true;
let number = if condition {
5
} else {
6
};

println!("The value of number is: {}", number);
}

loops

loop

The loop keyword tells Rust to execute a block of code over and over again forever or until you explicitly tell it to stop.

fn main() {
let mut counter = 0;

let result = loop {
counter += 1;

if counter == 10 {
break counter * 2;
}
};

assert_eq!(result, 20);
}

while

fn main() {
let mut number = 3;

while number != 0 {
println!("{}!", number);

number = number - 1;
}

println!("LIFTOFF!!!");
}

for

fn main() {
let a = [10, 20, 30, 40, 50];

for element in a.iter() {
println!("the value is: {}", element);
}
}
fn main() {
for number in (1..4).rev() {
println!("{}!", number);
}
println!("LIFTOFF!!!");
}

macro system

macros look like functions, except that their name ends with a bang !
Rust macros are expanded into abstract syntax trees, rather than string preprocessing, so you don’t get unexpected precedence bugs.

// This is a simple macro named `say_hello`.
macro_rules! say_hello {
// `()` indicates that the macro takes no argument.
() => (
// The macro will expand into the contents of this block.
println!("Hello!");
)
}

fn main() {
// This call will expand into `println!("Hello");`
say_hello!()
}

naming convention

Constants

use all uppercase with underscores between words

#![allow(unused_variables)]
fn main() {
const MAX_POINTS: u32 = 100_000;
}

引用依赖库

packages from crate.io

Cargo.toml 里面添加

[dependencies]
webbrowser = "0.2.2"

在rust源文件中引入 crate。

extern crate webbrowser;

packages from git repository

如果不加branch=”next”,则默认获取最新的commit,当然可以用rev、tag、branch来指定不同的版本。

[dependencies]
rand = { git = "https://github.com/rust-lang-nursery/rand", branch = "next" }

packages from local path

如果不加version=”0.1.0”,则不会进行版本检查。

[dependencies]
my_crate_name = { path = "../my-crate-directory", version = "0.1.0" }

package version

版本号还可以有另外一种crate格式,这种格式^x.y.z允许升级到与要求版本号兼容的最新版本上。

^1.2.3 := >=1.2.3 <2.0.0
^1.2 := >=1.2.0 <2.0.0

版本号还支持另一种Tilde格式,这种格式~x.y.z指定了最低版本号要求。

~1.2.3 := >=1.2.3 <1.3.0
~1.2 := >=1.2.0 <1.3.0
~1 := >=1.0.0 <2.0.0

版本号支持通配符。

* := >=0.0.0
1.* := >=1.0.0 <2.0.0
1.2.* := >=1.2.0 <1.3.0

update a project with dependencies

cargo update