Rust入门教程:目录
本文适合有一定基础的读者。
sample:
fn main(){
println("Hello world!");
}
rustc -V
cargo -V
cargo new greeting
创建greeting工程目录cargo build
构建工程cargo run
运行构建系统和包管理器。
tasks.json
, launch.json
fn main(){
int a = 12;
println("a is {}, {{}}", a);
}
{{
和}}
类似于转义字符,输出{}
let a=123
和a=123
->更改值let mut a = 123;
let a = 123
->let a = 234
let a: u64 = 123
u64
无符号64位整型变量位长度 | 有符号 | 无符号 |
---|---|---|
8-bit | i8 | u8 |
16-bit | i16 | u16 |
32-bit | i32 | u32 |
64-bit | i64 | u64 |
128-bit | i128 | u128 |
arch | isize | usize |
注意:
Rust 不支持 ++ 和 --,因为这两个运算符出现在变量的前后会影响代码可读性,减弱了开发者对变量改变的意识能力。
char 类型大小为 4 个字节
必须要用utf-8
()
包裹let tup: (i32, f64, u8) = (500, 6.4, 1);
let (x, y, z) = tup
let c:[i32;5]
长度5的i32数组let d = [3; 5]
即为let d = [3, 3, 3, 3, 3]
///
可以作为说明文档的开头cargo doc
可以将说明注释转换成HTML格式的说明文档fn (param:type) -> returntype{return}
fn another(x: i32, y: i32){}
let y = {
let x = 3;
x + 1
};
x + 1
之后没有分号,否则它将变成一条语句!fn main() {
fn five() -> i32 {
5
}
println!("five() 的值为: {}", five());
}
fn add(a: i32, b: i32) -> i32 {
return a + b;
}
if a < 0
, else if a < 0
for i in a.iter() {}
,a是数组fn main() {
let a = [10, 20, 30, 40, 50];
for i in a.iter() {
println!("值为 : {}", i);
}
}
fn main() {
let a = [10, 20, 30, 40, 50];
for i in 0..5 {
println!("a[{}] = {}", i, a[i]);
}
}
fn main() {
let s = ['R', 'U', 'N', 'O', 'O', 'B'];
let mut i = 0;
loop {
let ch = s[i];
if ch == 'O' {
break;
}
println!("\'{}\'", ch);
i += 1;
}
}
fn main() {
let s = ['R', 'U', 'N', 'O', 'O', 'B'];
let mut i = 0;
let location = loop {
let ch = s[i];
if ch == 'O' {
break i;
}
i += 1;
};
println!(" \'O\' 的索引为 {}", location);
}
变量与数据交互方式主要有移动(Move)和克隆(Clone)两种
发生交互的数据在堆中:
let s1 = String::from("hello");
let s2 = s1;
fn main() {
let s1 = String::from("hello");
let s2 = s1.clone();
println!("s1 = {}, s2 = {}", s1, s2);
}
fn main() {
let s1 = String::from("hello");
let s2 = &s1;
println!("s1 is {}, s2 is {}", s1, s2);
}
fn main() {
let s1 = String::from("hello");
let s2 = &s1;
let s3 = s1;
println!("{}", s2);
}
这段程序不正确:因为 s2 租借的 s1 已经将所有权移动到 s3,所以 s2 将无法继续租借使用 s1 的所有权。如果需要使用 s2 使用该值,必须重新租借:
fn main() {
let s1 = String::from("hello");
let mut s2 = &s1;
let s3 = s2;
s2 = &s3; // 重新从 s3 租借所有权
println!("{}", s2);
}
这段程序是正确的。
fn main() {
let mut s1 = String::from("run");
// s1 是可变的
let s2 = &mut s1;
// s2 是可变的引用
s2.push_str("oob");
println!("{}", s2);
}
let mut s = String::from("hello");
let r1 = &mut s;
let r2 = &mut s;
println!("{}, {}", r1, r2);
这段程序不正确,因为多重可变引用了 s。
野指针。
切片(Slice)是对数据值的部分引用。
sample:
fn main() {
let s = String::from("broadcast");
let part1 = &s[0..5];
let part2 = &s[5..9];
println!("{}={}+{}", s, part1, part2);
}
let slice = &s[0..3];
let s1 = String::from("hello");
let s2 = &s1[..];
struct Site {
domain: String,
name: String,
nation: String,
found: u32
}
let domain = String::from("www.runoob.com");
let name = String::from("RUNOOB");
let runoob = Site {
domain, // 等同于 domain : domain,
name, // 等同于 name : name,
nation: String::from("China"),
traffic: 2013
..runoob
};
struct Color(u8, u8, u8);
struct Point(f64, f64);
let black = Color(0, 0, 0);
let origin = Point(0.0, 0.0);
fn main() {
struct Color(u8, u8, u8);
struct Point(f64, f64);
let black = Color(0, 0, 0);
let origin = Point(0.0, 0.0);
println!("black = ({}, {}, {})", black.0, black.1, black.2);
println!("origin = ({}, {})", origin.0, origin.1);
}
#[derive(Debug)]
,之后在 println 和 print 宏中就可以用 {:?}
占位符输出一整个结构体{:#?}
#[derive(Debug)]
struct Rectangle {
width: u32,
height: u32,
}
fn main() {
let rect1 = Rectangle { width: 30, height: 50 };
println!("rect1 is {:?}", rect1);
}
struct Rectangle {
width: u32,
height: u32,
}
impl Rectangle {
fn area(&self) -> u32 {
self.width * self.height
}
}
fn main() {
let rect1 = Rectangle { width: 30, height: 50 };
println!("rect1's area is {}", rect1.area());
struct Rectangle {
width: u32,
height: u32,
}
impl Rectangle {
fn area(&self) -> u32 {
self.width * self.height
}
fn wider(&self, rect: &Rectangle) -> bool {
self.width > rect.width
}
}
fn main() {
let rect1 = Rectangle { width: 30, height: 50 };
let rect2 = Rectangle { width: 40, height: 20 };
println!("{}", rect1.wider(&rect2));
}
#[derive(Debug)]
struct Rectangle {
width: u32,
height: u32,
}
impl Rectangle {
fn create(width: u32, height: u32) -> Rectangle {
Rectangle { width, height }
}
}
fn main() {
let rect = Rectangle::create(30, 50);
println!("{:?}", rect);
}
结构体可以值作为一种象征而无需任何成员struct UnitStruct;
sample:
#[derive(Debug)]
enum Book {
Papery, Electronic
}
fn main() {
let book = Book::Papery;
println!("{:?}", book);
}
enum Book {
Papery(u32),
Electronic(String),
}
let book = Book::Papery(1001);
let ebook = Book::Electronic(String::from("url://..."));
enum Book {
Papery { index: u32 },
Electronic { url: String },
}
let book = Book::Papery{index: 1001};
fn main() {
enum Book {
Papery {index: u32},
Electronic {url: String},
}
let book = Book::Papery{index: 1001};
let ebook = Book::Electronic{url: String::from("url...")};
match book {
Book::Papery { index } => {
println!("Papery book {}", index);
},
Book::Electronic { url } => {
println!("E-book {}", url);
}
}
}
// Papery book 1001
对非枚举类进行分支选择时必须注意处理例外情况,即使在例外情况下没有任何要做的事 . 例外情况用下划线 _ 表示:
fn main() {
let t = "abc";
match t {
"abc" => println!("Yes"),
_ => {},
}
}
用于填补 Rust 不支持 null 引用的空白.
enum Option {
Some(T),
None,
}
let opt = Option::Some("Hello");
fn main() {
let opt = Option::Some("Hello");
match opt {
Option::Some(something) => {
println!("{}", something);
},
Option::None => {
println!("opt is nothing");
}
}
}
fn main() {
let opt: Option<&str> = Option::None;
match opt {
Option::Some(something) => {
println!("{}", something);
},
Option::None => {
println!("opt is nothing");
}
}
}
// prototype
let i = 0;
match i {
0 => println!("zero"),
_ => {},
}
// standard
if let 匹配值 = 源变量 {
语句块
}
//apply
fn main() {
enum Book {
Papery(u32),
Electronic(String)
}
let book = Book::Electronic(String::from("url"));
if let Book::Papery(index) = book {
println!("Papery {}", index);
} else {
println!("Not papery book");
}
}
Rust 中有三和重要的组织概念:箱、包、模块。
mod nation {
mod government {
fn govern() {}
}
mod congress {
fn legislate() {}
}
mod court {
fn judicial() {}
}
}
tree construction:
nation
├── government
│ └── govern
├── congress
│ └── legislate
└── court
└── judicial
::
分隔crate::nation::government::govern();
mod nation {
pub mod government {
pub fn govern() {}
}
mod congress {
pub fn legislate() {}
}
mod court {
fn judicial() {
super::congress::legislate();
}
}
}
fn main() {
nation::government::govern();
}
mode module;
引入use path as xx
当前作用域与别名mod nation {
pub mod government {
pub fn govern() {}
}
pub use government::govern;
}
fn main() {
nation::govern();
}
mod nation {
pub mod government {
pub fn govern() {}
}
pub fn govern() {}
}
use crate::nation::government::govern;
use crate::nation::govern as nation_govern;
fn main() {
nation_govern();
govern();
}
use std::f64::consts::PI;
fn main() {
println!("{}", (PI / 2.0).sin());
}
panic!("error");
不再执行enum Result {
Ok(T),
Err(E),
}
use std::fs::File;
use std::fs::File;
fn main() {
let f = File::open("hello.txt");
if let Ok(file) = f {
println!("File opened successfully.");
} else {
println!("Failed to open the file.");
}
}
use std::fs::File;
fn main() {
let f1 = File::open("hello.txt").unwrap();
let f2 = File::open("hello.txt").expect("Failed to open.");
}
fn f(i: i32) -> Result {
if i >= 0 { Ok(i) }
else { Err(false) }
}
fn main() {
let r = f(10000);
if let Ok(v) = r {
println!("Ok: f(-1) = {}", v);
} else {
println!("Err");
}
}
use std::io;
use std::io::Read;
use std::fs::File;
fn read_text_from_file(path: &str) -> Result {
let mut f = File::open(path)?;
let mut s = String::new();
f.read_to_string(&mut s)?;
Ok(s)
}
fn main() {
let str_file = read_text_from_file("hello.txt");
match str_file {
Ok(s) => println!("{}", s),
Err(e) => {
match e.kind() {
io::ErrorKind::NotFound => {
println!("No such file");
},
_ => {
println!("Cannot read the file");
}
}
}
}
}
fn max(array: &[i32]) -> i32 {
let mut max_index = 0;
let mut i = 1;
while i < array.len() {
if array[i] > array[max_index] {
max_index = i;
}
i += 1;
}
array[max_index]
}
fn main() {
let a = [2, 4, 6, 3, 1];
println!("max = {}", max(&a));
}
这是一个简单的取最大值程序,可以用于处理 i32 数字类型的数据,但无法用于 f64 类型的数据。通过使用泛型我们可以使这个函数可以利用到各个类型中去。但实际上并不是所有的数据类型都可以比大小,所以接下来一段代码并不是用来运行的,而是用来描述一下函数泛型的语法格式:
fn max(array: &[T]) -> T {
let mut max_index = 0;
let mut i = 1;
while i < array.len() {
if array[i] > array[max_index] {
max_index = i;
}
i += 1;
}
array[max_index]
}
struct Point {
x: T,
y: T
}
//这是一个点坐标结构体,T 表示描述点坐标的数字类型。我们可以这样使用:
let p1 = Point {x: 1, y: 2};
let p2 = Point {x: 1.0, y: 2.0};
struct Point {
x: T1,
y: T2
}
enum Option {
Some(T),
None,
}
enum Result {
Ok(T),
Err(E),
}
struct Point {
x: T,
y: T,
}
impl Point {
fn x(&self) -> &T {
&self.x
}
}
fn main() {
let p = Point { x: 1, y: 2 };
println!("p.x = {}", p.x());
}
,因为它后面的 T 是以之为榜样的impl Point {
fn x(&self) -> f64 {
self.x
}
}
// impl 块本身的泛型并没有阻碍其内部方法具有泛型的能力
impl Point {
fn mixup(self, other: Point) -> Point {
Point {
x: self.x,
y: other.y,
}
}
}
//方法 mixup 将一个 Point 点的 x 与 Point 点的 y 融合成一个类型为 Point 的新点。
特性(trait)概念接近于 Java 中的接口(Interface),但两者不完全相同。特性与接口相同的地方在于它们都是一种行为规范,可以用于标识哪些类有哪些方法。
trait Descriptive {
fn describe(&self) -> String;
}
struct Person {
name: String,
age: u8
}
impl Descriptive for Person {
fn describe(&self) -> String {
format!("{} {}", self.name, self.age)
}
}
impl <特性名> for <所实现的类型名>
这是特性与接口的不同点:接口只能规范方法而不能定义方法,但特性可以定义方法作为默认方法,因为是"默认",所以对象既可以重新定义方法,也可以不重新定义方法使用默认的方法:
trait Descriptive {
fn describe(&self) -> String {
String::from("[Object]")
}
}
struct Person {
name: String,
age: u8
}
impl Descriptive for Person {
fn describe(&self) -> String {
format!("{} {}", self.name, self.age)
}
}
fn main() {
let cali = Person {
name: String::from("Cali"),
age: 24
};
println!("{}", cali.describe());
}
生命周期机制是与所有权机制同等重要的资源管理机制。
{
let r;
{
let x = 5;
r = &x;
}
println!("r: {}", r);
}
&i32 // 常规引用
&'a i32 // 含有生命周期注释的引用
&'a mut i32 // 可变型含有生命周期注释的引用
在 Rust 中主函数是个无参函数,环境参数需要开发者通过 std::env 模块取出
fn main() {
let args = std::env::args();
println!("{:?}", args);
}
use std::fs;
fn main() {
let text = fs::read_to_string("D:\\text.txt").unwrap();
println!("{}", text);
}
use std::fs;
fn main() {
fs::write("D:\\text.txt", "FROM RUST PROGRAM")
.unwrap();
}
use std::thread;
use std::time::Duration;
fn spawn_function() {
for i in 0..5 {
println!("spawned thread print {}", i);
thread::sleep(Duration::from_millis(1));
}
}
fn main() {
thread::spawn(spawn_function);
for i in 0..3 {
println!("main thread print {}", i);
thread::sleep(Duration::from_millis(1));
}
}
@Copyright: 菜鸟教程