cargo new xxx;cargo build;cargo run;cargo check(检查语法)
执行的文件在target的debug内
变量
mut 可变变量
隐藏,在同一个代码段同名变量定义时具有隐藏性,即第二次定义后使用的是使用的第二次定义的类型,将第一次定义的变量隐藏
const 定义常量: const MAXX:u32 = 10000;
数据类型(编译器具有自动推导功能,不必须写上变量类型)
bool型
char型在rust语言里面是32位的!char可以是一个汉字
i8 i16 i32 i64 u8 u16 u32 u64 f32 f64
自适应类型(与机器平台有关系) isize usize println!("max = {}",usize::max_value());
数组 [Type; size] size也是数组类型的一部分
let arr: [u32; 5] = [1,2,3,4,5];
show(arr); // 这里会报错,因为size不一致而size也是数组类型的一个部分
fn show(arr:[u32;3]){
for i in &arr{
println!("{}",i);
}
}
元组 复合类型
let tup: (i32,f32,char) = (-3,3.69,‘赞‘);
println!("{}",tup.0);
println!("{}",tup.1);
println!("{}",tup.2);
let tup = (-3,3.69,‘赞‘); //自动推导
//元组可拆解
let (x,y,z) = tup;
println!("{}",x);
函数 蛇形命名法 常量大写字母 类的首字母大写 一般函数等用小写字母
fn other_fun(){
println!("This is a function!");
}
fn other_fun1(a:i32,b:u32){
println!("a = {},b = {}",a,b);
}
fn other_fun2(a:i32,b:i32) -> i32{
let result = a + b;
return result;
}
fn other_fun3(a:i32,b:i32) -> i32{
a + b
}
函数定义的时候传入的变量需要有类型
语句 执行操作 但是不返回值得指令
let y = 1; //语句,不返回值
let x = (let y = 1); //错误的,因为无返回值,与C++不一样
表达式 会计算一些值
let y = {
let x = 1;
x + 1; //错误 无发返回
x + 1 //正确,输出y为2
}
控制流
? println!("y==other");
if y == 1 {
println!("y==1");
}else{
println!("y!=1");
}
if y == 1 {
println!("y==1");
}else if y == 0{
println!("y==0");
}else{
println!("y==other");
}
let中也可以使用if,且if else中得类型应该保持一致
let condition = true;
let x = if condition{
5
}else{
6
};
println!("{}",x);
loop loop 也可以赋值给let
let mut counter = 0;
loop{
println!("loop");
if counter == 10{
break;
}
counter = counter + 1;
}
let mut c = 1;
let result = loop{
c += 1;
if c == 20{
break c * 2;
}
};
println!("{}",result); //result为40
while 循环
let mut i = 0;
while i !=10 {
i += 1;
}
println!("i={}",i);
for 循环
let arr:[u32;5] = [1,2,3,4,5];
//用迭代器
for element in &arr{
println!("element={}",element);
}
所有权
堆和栈
编译的时候数据的类型大小是固定的,就是分配在栈上的
编译的时候数据的类型大小不是固定的,就是分配在堆上的
作用域: {}
let x:i32 = 1;
{
let y:i32 = 2;
println!("{}",x);
}
println!("{}",y);
// y的作用域在{}之内,因此下面无法访问到y的值
借用/移动
let s1 = String::from("abc");
let s2 = s1;
println!("{}",s1);//报错
类似于C++中的浅拷贝,只是对指针复制,没有对指针所指的区域的进行复制
RUST中拷贝后默认s1无效,即s1的所有权移植给了s2,因此s1处于空,无效状态
同时RUST中string存在内存回收,在离开作用域时会自动调用drop完成内存的回收操作,类似于类的析构
clone/深拷贝
let s1 = String:from("abc");
let s2 = s1.clone();
再访问s1可以访问,clone可以拷贝数据即进行深拷贝
栈上的数据拷贝
let a = 1;
let b = a;
println!("a = {} , b = {}",a,b);
在栈上的数据执行等号的时候默认进行copy(相当于深拷贝)
类似于C++中int char等相等之后也可以用,但是class类需要自定义深拷贝clone函数
常用的具有copy trait有
所有的整型 浮点型 布尔型 字符类型(char) 元组 数组
函数和作用域
fn fun(some_string: String){
println!("{}",some_string);
}
fn fun2(i:i32){
println!("i = {}",i);
}
fn main(){
let s = String::from("hello");
fun(s);
println!("{}",s);//报错 S已经在离开作用域的时候被drop回收了
let x = 5;
fun2(x);
println!("{}",x); //可以使用,x分配在栈上,是直接进行copy而不是clone
}
引用和借用
fn main(){
let s1 = gives_ownership();
let s2 = String::from("hello");
let s3 = takes_and_gives_back(s2);
println!("Hello world!");
}
fn gives_ownership() -> String {
let s = String::from("hello");
s
}
fn takes_and_gives_back(s: String) -> String {
s
}
因为是调用gives_ownership函数,因此调用后将s的作用域返回给s1
因为s2的使用权将传递给s3,所以如果在最后再次调用s2会发现无法使用
会发现上面十分麻烦,所以RUST中存在了引用这个功能
// 引用: 用法&,
// 让我们创建一个指向值的应用,但是并不拥有它,因为不拥有这个值,所以,当引用离开其值指向的作用域后也不会被丢弃
// 借用:&mut
fn length(s: &String) -> usize{
s.len()
}
fn modify_s(s: &mut String){
s.push_str(",world");
}
fn main(){
let mut s1 = String::from("hello");
let len = length(&s1);
let s = &s1;
println!("s = {}",s);
println!("s1 = {}",s1);
println!("len = {}",len);
modify_s(&mut s1);
println!("s1 = {}",s1);
}
引用无法对值进行修改,只是可以去完成访问,如果需要修改一类操作,需要借用
RUST推荐每个变量只有一个数据拥有权(引用or借用),即不可变引用和可变借用不可以针对于同一个变量同时存在,也就是可读和可读可写不能同时存在
但是当我对其中某一个运用完后可以调用另外一个,即可变以后要重新去进行借用,示例代码如下
fn main(){
let mut s = String::from("hello");
let s1 = &s;
println!("{}",s1);
let s2 = &mut s;
s2.push_str(",world!");
println!("{}",s2);
}
泉水引用 Wrong
fn main(){
let ref_s = dangle();
}
fn bcyx() -> &String{
let s = String::from("hello");
&s
}
作用域在函数内回收掉了,但是引用仍然指向内存,并且返回引用,会报错
slice
let s = String::from("hello world!");
let h = &s[0..5];
let h = &s[..5];
let h = &s[0..=4];
let h = &s[..=4];
let w = &s[6..];//第六位到结尾
let a = [1,2,3,4];
let sss = &a[1..3];
println!("sss1 = {}",sss[0]);
println!("h = {}",h); //输出hello 上面四个情况均一致
结构体
定义结构体
#[derive(Debug)]
struct User {
name: String,
count:String,
nonce: u64,
active: bool,
}
创建结构体实例
let xiaoming = User {
name: String::from("xiaoming"),
count: String::from("80001000"),
nonce: 10000,
active:true,
};
println!("xiaoming = {:?}", xiaoming);//横着打出来
println!("xiaoming = {:#?}", xiaoming);//结构体
修改结构体字段
let mut xiaohuang = User {
name: String::from("xiaohuang"),
count: String::from("80001000"),
nonce: 10000,
active:true,
};
xiaohuang.nonce = 20000;
参数名字和字段名字同名的简写方法
let name = String::from("xiaoxiao");
let count = String::from("89077777");
let nonce = 200000;
let active = false;
let user1 = User {
name,
count,
nonce,
active,
};
从其他结构体创建实例
let user2 = User {
name: String::from("user2"),
..user1
};
println!("name = {}", user2.name);
println!("nonce = {}", user2.nonce);
元组结构体
//(1)字段没有名字直接.0和.1等
//(2)圆括号
struct Point(i32, i32);
let a = Point(10, 20);
let b = Point(30, 11);
println!("a.x = {}, a.y = {}", a.0, a.1);
没有任何字段的类单元结构体
struct A{};
打印结构体
//结构体前添加 #[derive(Debug)]
# [derive(Debug)]
println!("xiaoming = {:?}",xiaoming); //横着打印出来
println!("xiaoming = {:#?}",xiaoming) //自动换行打印
方法
# [derive(Debug)]
struct Dog {
name: String,
weight: f32,
height: f32,
}
//简单理解成C++中的类函数
impl Dog {
fn get_name(&self) -> &str {
&(self.name[..])
}
fn get_weight(&self) -> f32 {
self.weight
}
//fn get_height(&self) -> f32 {
// self.height
//}
fn show() {
println!("oh oh oh");
}
}
impl Dog{
fn get_height(&self) -> f32 {
self.height
}
}
fn main() {
let dog = Dog {
name: String::from("wangcai"),
weight: 100.0,
height: 70.5,
};
println!("dog = {:#?}", dog);
println!("name = {}", dog.get_name());
println!("weight = {}", dog.get_weight());
println!("height = {}", dog.get_height());
Dog::show();
println!("Hello, world!");
}
枚举类型与模式匹配
//1、类似于c语言的方式定义
enum IpAddrKind {
V4,
V6,
}
struct IpAddr {
kind: IpAddrKind,
address: String,
}
//2、rust语言提倡的方式定义
enum IpAddr2 {
V4(String),
V6(String),
}
//3、可以是不同类型
enum IpAddr3 {
V4(u8, u8, u8, u8),
V6(String),
}
//4、经典用法
enum Message {
Quit,
Move{x: i32, y: i32},
Write(String),
Change(i32, i32, i32),
}
//等同于
//struct QuitMessage; //类单元结构体
//struct MoveMessage {
// x: i32,
// y: i32,
//}
//struct WriteMessage(String)
//struct Change(i32, i32, i32)
//5、枚举类型的方法以及match
impl Message {
fn prin(&self) {
match *self {
Message::Quit => println!("Quit"),
Message::Move{x, y} => println!("Move x = {}, y = {}", x, y),
Message::Change(a, b, c) => println!("Change a = {}, b = {}, c = {}", a, b, c),
_ => println!("Write")
//Message::Write(&s) => println!("Write = {}", s)
}
}
}
fn main() {
let i1 = IpAddr {
kind: IpAddrKind::V4,
address: String::from("127.0.0.1"),
};
let i2 = IpAddr {
kind: IpAddrKind::V6,
address: String::from("::1"),
};
let i1 = IpAddr2::V4(String::from("127.0.0.1"));
let i2 = IpAddr2::V6(String::from("::1"));
let i1 = IpAddr3::V4(127, 0, 0, 1);
let i2 = IpAddr3::V6(String::from("::1"));
let quit = Message::Quit;
quit.prin();
let mo = Message::Move{x: 10, y: 20};
mo.prin();
let wri = Message::Write(String::from("Hello"));
wri.prin();
let change = Message::Change(1, 2, 3);
change.prin();
println!("Hello, world!");
}
Option
option是标准库定义的一个枚举类型
match一定要处理完Option中所有的情况
enum Option<T> {
Some(T),
None,
}
fn main(){
let some_number = Some(5);
let some_string = Some(String::from("123"));
let absent_number: Option<i32> = None;
let x:i32 = 5;
let y:Option<i32> = Some(5);
let mut temp:i32 = 0
// let sum = x + y; x和y不是同一个类型
match y{
Some(i) => {temp = i ;}
None => {println!("No");}
}
let sum = x + temp;
let result = plus_one(y);
match result {
Some(i) => println!("result = {}", i),
None => println!("nothing"),
};
println!("sum = {}",sum);
if let Some(value) = plus_one(y) {
println!("value = {}", value);
}
if let Some(value) = plus_one(y) {
println!("value = {}", value);
} else {
println!("do nothing");
}
}
fn plus_one(x: Option<i32>) -> Option<i32> {
match x {
None => None,
Some(x) => Some(x+1),
}
}
Vector
fn main(){
// 1. 创建空的vector
let mut v:Vec<i32> = Vec::new();
v.push(1);
// 2. 创建包含初始值的vector
let v = vec![1,2,3];
// 3. 丢弃vector
{
let v1 = vec![1,2,3];
}
// 4. 读取元素
let one: &i32 = &v[1];
println!("{}",one);
println!("{}",*one);
//上面这两种输出的形式一样 应该是存在自动转换功能
match v.get(1){
Some(Value) => println!("value = {}",value),
_ => None,
}
// 5. 更新
let mut v2:Vec<i32> = Vec::new();
v2.push(1);
v2.push(2);
v2.push(3);
// 6. 遍历
// 不可变的遍历
for i in &v2{
println!("{}",i);
}
// 可变的遍历
for i in &mut v2{
*i += 1;
println!("{}",i);
}
// 7. 使用枚举
enum Context {
Text(String),
Float(f32),
Int(i32),
};
let c = vec![
Context::Text(String::from("string")),
Context::Int(-1),
Context::Float(0.001)
];
// 8. 补充
let mut v = vec![1, 2, 3, 4, 5];
let first = &v[0];
v.push(6);
//报错!!!!
//不可变引用后使用可变引用不能再使用不可变引用了!!!!
println!("first = {}", first);
println!("Hello, world!");
}
String
//1、创建一个空String
//2、通过字面值创建一个String
//2.1、使用String::from()
//2.2、使用str的方式
//3、更新String
//3.1、push_str
//3.2、push
//3.3、使用“+”合并字符串
//3.4、使用format!
//4、String 索引
//5、str 索引
//6、遍历
//6.1、chars
//6.2、bytes
fn main() {
let mut s0 = String::new();
s0.push_str("hello");
println!("s0 = {}", s0);
let s1 = String::from("init some thing");
println!("{}", s1);
let s1 = "init some thing".to_string();
println!("{}", s1);
let mut s2 = String::from("hello");
s2.push_str(", world");
let ss = " !".to_string();
s2.push_str(&ss);//用ss的引用
println!("{}", s2);
println!("ss = {}", ss);
let mut s2 = String::from("tea");
s2.push(‘m‘);
//s2.push(‘mx‘); //error
//s2.push("x"); //error
println!("{}", s2);
let s1 = "hello".to_string();
let s2 = String::from(", world");
let s3 = s1 + &s2;
println!("s3 = {}", s3);
//println!("s1 = {}", s1);
println!("s2 = {}", s2);
let s341 = String::from("tic");
let s342 = String::from("tac");
let s343 = String::from("toe");
let s344 = format!("{}-{}-{}", s341, s342, s343); //format!和println!类似
println!("s344 = {}", s344);
println!("s341 = {}", s341);
println!("s342 = {}", s342);
println!("s343 = {}", s343);
let s4 = String::from("hello");
//let s41 = s4[0];
println!("s4.len = {}", s4.len());
let s4 = String::from("你好");
println!("s4.len = {}", s4.len());
//let s41 = s4[0];
let hello = "你好";
let h5 = &hello[0..3];
println!("h5 = {}", h5);
//let h6 = &hello[0..2];
//println!("h6 = {}", h6);
//chars
for c in s4.chars() {
println!("c = {}", c);
}
println!("+++++++++++++++");
//bytes
for b in s4.bytes() {
println!("b = {}", b);
}
println!("+++++++++++++++");
println!("Hello, world!");
}
HashMap
//1、HashMap<K, V>
//2、创建HashMap
//3、读取
//4、遍历
//5、更新
use std::collections::HashMap;
fn main() {
let mut scores: HashMap<String, i32> = HashMap::new();
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Red"), 20);
let keys = vec![String::from("Blue"), String::from("Red")];
let values = vec![10, 20];
let scores: HashMap<_, _> = keys.iter().zip(values.iter()).collect();
let k = String::from("Blue");
if let Some(v) = scores.get(&k) { //get 返回的是一个Option
println!("v = {}", v);
}
let k = String::from("Yellow");
let v = scores.get(&k);
match v {
Some(value) => println!("v = {}", value),
None => println!("None"),
}
println!("++++++++++++");
//遍历:会以任意的顺序遍历出来
for (key, value) in &scores {
println!("{}, {}", key, value);
}
println!("++++++++++++");
//直接插入
let mut ss = HashMap::new();
ss.insert(String::from("one"), 1);
ss.insert(String::from("two"), 2);
ss.insert(String::from("three"), 3);
ss.insert(String::from("one"), 3);//覆盖前者
println!("{:?}", ss);
//键不存在的时候才插入
let mut ss1 = HashMap::new();
ss1.insert(String::from("one"), 1);
ss1.insert(String::from("two"), 2);
ss1.insert(String::from("three"), 3);
ss1.entry(String::from("one")).or_insert(3);
println!("ss1 = {:?}", ss1);
//根据旧值来更新一个值
let text = "hello world wonderful world";
let mut map = HashMap::new();
for word in text.split_whitespace() {
let count = map.entry(word).or_insert(0);
*count += 1;
}
println!("map = {:?}", map);
println!("Hello, world!");
}
模块
定义
包和crate
mod factory {
pub mod produce_refrigerator {
pub fn produce_re() {
println!("produce refrigerator!");
}
}
mod produce_washing_machine {
fn produce_washing() {
println!("produce washing machine!");
}
}
}
fn main() {
factory::produce_refrigerator::produce_re();
println!("Hello, world!");
}
模块2
创建好的项目里cargo new --lib mylib
//factory.rs
pub mod produce_refrigerator {
pub fn produce_re() {
println!("produce refrigerator!");
}
}
pub mod produce_washing_machine {
pub fn produce_washing() {
println!("produce washing machine!");
}
pub fn produce_re() {
println!("produce washing machine!");
}
}
//lib.rs
pub mod factory;
先在main的cargo里面添加
[dependencies]
mylib = {path = "./mylib"}
在main.rs中利用
//use mylib::factory::produce_refrigerator;
//use mylib::factory::produce_refrigerator::produce_re;
//use mylib::factory::produce_washing_machine;
//use mylib::factory::produce_washing_machine as A;
use mylib::factory::*;
fn main() {
mylib::factory::produce_refrigerator::produce_re(); //绝对路径
produce_refrigerator::produce_re(); //使用use
produce_washing_machine::produce_re();
//A::produce_re();
println!("Hello, world!");
}
模块3
mod modA {
#[derive(Debug)]
pub struct A {
pub number: i32,
name: String,
}
impl A {
pub fn new_a() -> A {
A {
number: 1,
name: String::from("A"),
}
}
pub fn print_a(&self) {
println!("number: {}, name: {}", self.number, self.name);
}
}
pub mod modB {
pub fn print_B() {
println!("B");
}
pub mod modC {
pub fn print_C() {
println!("C");
super::print_B();
}
}
}
}
//use modA::A;
use modA::A as A1;
fn main() {
//let a = modA::A::new_a();
//let a = A::new_a();
let a = A1::new_a();
a.print_a();
let number = a.number;
//let name = a.name;
println!("+++++++++++++");
modA::modB::modC::print_C();
println!("Hello, world!");
}
模块4
错误1
//1、rust语言将错误分为两个类别:可恢复错误和不可恢复错误
//(1)可恢复错误通常代表向用户报告错误和重试操作是合理的情况,例如未找到文件。rust中使用Result<T,E>来实现。
//(2)不可恢复错误是bug的同义词,如尝试访问超过数组结尾的位置。rust中通过panic!来实现。
//2、panic!
//3、使用BACKTRACE=1
//4、Result<T, E>
//enum Result<T, E> {
// Ok(T),
// Err(E),
//}
//5、简写
use std::fs::File;
fn main() {
//let f = File::open("hello.txt");
//let r = match f {
// Ok(file) => file,
// Err(error) => panic!("error: {:?}", error),
//};
//let f = File::open("hello.txt").unwrap();
let f = File::open("hello.txt").expect("Failed to open hello.txt");
//panic!("crash here");
}
错误2
//1、当编写一个函数,但是该函数可能会失败,此时除了在函数中处理错误外,还可以将错误传给调用者,让调用者决定如何处理,这被称为传播错误。
//2、传播错误的简写方式,提倡的方式
//3、更进一步的简写
//4、什么时候用panic!,什么时候用Result
//(1)示例、代码原型、测试用panic!\unwrap\expect
//(2)实际项目中应该用Result
//5、Option和Result
use std::io;
use std::io::Read;
use std::fs::File;
fn main() {
println!("Hello, world!");
let r = read_username_from_file();
match r {
Ok(s) => println!("s = {}", s),
Err(e) => println!("err = {:?}", e),
}
}
//fn read_username_from_file() -> Result<String, io::Error> {
// let f = File::open("hello.txt");
// let mut f = match f {
// Ok(file) => file,
// Err(error) => return Err(error),
// };
//
// let mut s = String::new();
// match f.read_to_string(&mut s) {
// Ok(_) => Ok(s),
// Err(error) => Err(error),
// }
//}
//
//fn read_username_from_file() -> Result<String, io::Error> {
// let mut f = File::open("hello.txt")?;
//
// let mut s = String::new();
// f.read_to_string(&mut s)?;
// Ok(s)
//}
fn read_username_from_file() -> Result<String, io::Error> {
let mut s = String::new();
File::open("hello.txt")?.read_to_string(&mut s)?;
Ok(s)
}
原文:https://www.cnblogs.com/buchiyexiao/p/14644505.html