赞
踩
Rust是一门新式的优秀的语言,这门语言一般用于替代C、C++进行硬件层面的开发或者是一些系统后台的开发,本文是Rust的快速入门。
Windows可以直接下载应用安装程序
如果是WIndows Linux 子系统,需要使用curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
安装过程缓慢,安装完成后,可以使用rustc进行测试。
使用cargo new helloWorld
创建HelloWorld程序
fn main() {
println!("Hello, world!");
}
其中fn是定义了一个函数,但是println!()是一个宏而不是一个函数,调用宏需要使用"!"
使用下方的命令進行编译,需要进入到项目文件夹中:
cargo build
编译如果没有出现问题的话会在target文件夹中生成一个编译后的结果,可以直接运行./target/debug/helloworld.exe
Rust虽然是一个静态类型(编译时就明确类型)强类型的语言,但是并不需要将变量进行显式的声明,而是直接可以使用下方的形式
let _x = 1
在Rust中会自动的识别这个变量的类型为int32,但是此时这个变量是一个不可变变量
fn main() {
let _x =1;
}
对于变量的输出则是采用println!("{}",x)
使用大括号的形式进行数据的输出和打印
不可变变量对于Rust下方代码是不可运行的。
fn main() {
let _x =1;
_x=2;
}
如果需要进行变量的常规变更,例如计数器这样的操作,需要使用下方的代码。在Rust中强制要求所有的默认变量都是不可以被二次赋值的,这也保证了Rust的安全和优势,同时在很多编译器语言中,SSA(静态单赋值)不允许二次变量值的变动,每次变量用完即丢。
fn main() {
let mut _x = 1;
_x = 2;
print!("{}", _x)
}
编译期就会进行计算,使用const 进行修饰
常量在Rust中存在以下特征:1. 不允许可变动(不能使用mut修饰)2. 任何地方都可以进行变量的声明 3. 常量只能设置为常量表达式
const _X: i32 = 1;
fn main() {
println!("{}", _X);
}
无符号整数:u8,u16……u64,usize(计算机系统有关)
有符号整数: i8, i16, i32,isize(计算机系统有关)
浮点数:f32、f64(速度大致相同)
布尔值(bool):一个字节:true、false
字符(char):Char是Unicode,大小4bytes大小(单引号)字符串(双引号)
数组:固定长度[],默认为长度一定的i32
fn main() {
let array: [i32; 5] = [1, 2, 3, 4, 5];
println!("{}", array[1]);
}
if:Rust中条件判定只能是布尔值
fn main() {
let number = 3;
if number < 5 {
println!("condition was true");
} else {
println!("condition was false");
}
}
可以仿照三元表达式
let number = 3;
//在Rust中Expression可以有返回值 (c 中statement只是标识状态,没有返回值)
let target = if number < 5 { 4 } else { 6 };//两个结果需要是统一的类型,因为Rust在编译时间就会确认变量的类型
println!("{}", target);
loop:
不显示的退出一直运行
fn main() {
let mut number = 3;
loop {
number += 1;
println!("{}", number);
if number == 10 {
break;
}
}
println!("loop ended");
}
while:
fn main() {
let mut number = 3;
while number<10 {
number += 1;
println!("{}", number);
}
}
for
fn main() {
let a = [1, 2, 3, 4, 5];
for u in a.iter() {
println!("{}", u);
}
}
struct User{
username: String,
age:u32
}
如果需要结构体进行修改,需要使用关键词mut进行修饰
struct User {
username: String,
age: i32
}
fn main() {
let user1 = User {
username: String::from("John"),
age: 30,
};
print!("{}",user1.username)
}
使用impl语法糖可以模拟面向对象的实现,方法的定义。
struct User { username: String, age: i32 } impl User { fn print_user(&self) { println!("{} is {}", self.username, self.age); } } fn main() { let user1 = User { username: String::from("John"), age: 30, }; user1.print_user() }
//std::cmp::PartialOrd 这个是类型的约束,可以比较大小
fn larger<T: std::cmp::PartialOrd>(a: T, b: T) -> T {
if a > b {
a
} else {
b
}
}
fn main() {
let number1 = 3;
let number2 = 4;
let max = larger(number1, number2);
println!("The largest number is {}", max);
}
Rust采用两个通用的枚举来完成错误处理和空返回(有的语言使用Null)为了解决空指针问题
Option 代表有或者无Some(T),None
Result<T,E> 代表成功或者失败Ok(T),Err(E)
需要使用匹配语法进行条件的判定
fn main() {
match std::env::home_dir() {
Some(data) => println!("option is some,data={:?}", data),
None => print!("option is none"),
}
match std::env::var("PATH") {
Ok(data) => print!("home env,data={}", data),
Err(err)=>print!("error is {}",err)
}
}
C: 手动管理(malloc和free)
GC:Go、Java
Rust:基于生命周期的半自动管理(所有权和生命周期)
在Rust中所有的变量只拥有唯一的所有者,所以下方的代码是不能运行的,因为string1被赋值给了string2,所以不能打印string1,因为已经转移到了string2
fn main() {
//存储在堆中
let string1=String::from("hello world");
//直接将string1的指向归属给了string2,而不是在堆中复制值
let string2=string1;
println!("{}",string1);
}
fn string_resver(s: String)->String {
s.chars().rev().collect()
}
fn main() {
let string1 = String::from("hello world");
let string2 = string_resver(string1);
println!("{}", string1);
println!("{}", string2);
}
上述代码是错误的代码,因为string1的所有权已经转移到了string_resver函数中,所以生命周期已经被销毁,所以需要使用到原变量的值,需要使用下方的代码。
fn string_resver(s: String)->(String,String){
(s.clone(), s.chars().rev().collect())
}
fn main() {
let string1 = String::from("hello world");
let (string3,string2) = string_resver(string1);
println!("{}", string3);
println!("{}", string2);
}
所以可以直接通过传递引用的方式进行参数的传递
fn string_resver(s: &String) -> String {
s.chars().rev().collect()
}
fn main() {
let string1 = String::from("hello world");
let string2 = string_resver(&string1);
println!("{}", string1);
println!("{}", string2);
}
1. 引用不会获取到数据的所有权
2. 默认情况下引用是不可变的
3. 同一时间最多只能存在一个可变引用(多线程中避免数据竞争)
fn string_resver(s: &mut String) {
s.push_str("!");
}
fn main() {
let mut string1 = String::from("hello world");
string_resver(&mut string1);
println!("{}", string1);
}
RefCell用来实现内部可变性,internal mutability,即数据可以在自身的方法中改变自身,但对外是不可变的。
Box, Rc, RefCell比较:
Rc,允许多重拥有,不可变借用,编译时检查
Box,单一拥有者,可变或不可变借用,编译时检查(Deref, DerefMut)
RefCell, 单一拥有者,可变或不可变借用,运行时检查。可变不可变是对外的,都可以在内部改变。其实是把不安全的操作包装在安全的接口中
Cargo.toml中保存的是项目依赖和项目信息,如果需要使用第三方的模块,则需要在dependencies中增加内容。
[dependencies]
rand = "0.8.3"
然后使用cargo run
命令会自动的进行依赖包的安装和构建。
官方的第一个练习:猜数字,使用到了rand模块
use std::io;
use rand::Rng;
fn main() {
println!("输入你需要选择的数字!");
let mut string_input = String::new();
io::stdin().read_line(&mut string_input).expect("读取失败");
println!("您输入的数目是{}", string_input);
let radom_number = rand::thread_rng().gen_range(1..101);
println!("随机数是{}", radom_number);
if string_input == radom_number.to_string() {
println!("恭喜你猜对了!");
} else {
println!("很遗憾你猜错了!");
}
}
在Rust中需要对比两个不同类型的数据,需要进行显式的类型转换例如.to_string()或者是.parse()
需要注意的是,在Rust中推荐的变量命名和函数命名类似于Python,需要进行下划线作为全部小写单词切分,而不是类似于Java,采用小写驼峰形式。
在Rust中存在一些特殊点:
let arr=[1;5]
(let arr=[1,1,1,1,1]
)let mut v:Vec<i32>=Vec::new()
或者可以创建指定长度的动态数组let mut v:Vec<i32>=Vec::with_capacity(10)
也可使用宏来创建let mut v = vec![0;10]
,使用push()方法加入数据,pop()方法删除,remove可以删除指定索引,并将后方所有元素左移。push_front()/push_back(),pop_front()/pop_back()
指向堆上字节序列指针as_ptr
,堆上字节长度len
,分配堆容量capacity
),如果对两个String类型的字符串使用“+/+=”会返回新的字符串,而不是追加字符串(String+str)。Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。