文件名称 | 版本号 | 作者 | 版本 | |
---|---|---|---|---|
Rust日常笔记_持续更新 | v1.0.7 | 学生宫布 | 8416837 | rust 1.44.1 cargo 1.46.0 rustup 1.11.0 |
Rust开发环境
安装基础环境
Win OS环境
使用Chocolatey
软件包工具安装Rust,Chocolatey
的安装教程见Chocolatey教程。或者使用其它方式安装,下载Rustup。
如果是巧克力方式安装:
执行:choco search rust
rust包被发现,但是我们不需要直接安装rust,先安装rustup
- 设置rustup国内镜像:
set RUSTUP_DIST_SERVER=https://mirrors.ustc.edu.cn/rust-static
set RUSTUP_UPDATE_ROOT=https://mirrors.ustc.edu.cn/rust-static/rustup
以上镜像配置当前页面有效。有可能设置镜像后报ssl
错误。
如果不起效,使用PowerShell设置:
$ENV:RUSTUP_DIST_SERVER='https://mirrors.ustc.edu.cn/rust-static'
$ENV:RUSTUP_UPDATE_ROOT='https://mirrors.ustc.edu.cn/rust-static/rustup'
choco install rustup --pre
输入yes
,开始安装
Installing rustup-init...
晚上安装时,在这个初始化卡住了
- 安装界面,查看方便点
choco install ChocolateyGUI
打开: - 查看rustup和cargo.Cargo:包管理器。类似npm、Java的Maven。
- rustup show 查看工具链
没有
看下存在的工具链,也可以增加工具链
rustup toolchain list
设置默认工具链
rustup default stable-x86_64-pc-windows-msvc
- 组件是必需的:
装上
rustup component add rust-src
很遗憾,不支持组件:
- 安装其它版本的
rustup toolchain install nightly-2019-01-17
orrustup toolchain add nightly
如果报ssl错误,则先不要用国内镜像
好的开始:
移除这个
rustup toolchain remove stable
设置新的默认
rustup default nightly
- 防止报错:找不到
link.exe
。请安装VCBuild tools 2015 - 检查编译器是否存在
rustc -V
:
LINUX OS
Ubuntu
脚本
curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf | sh # 执该命令即开始安装
source $HOME/.cargo/env # 重启console
rustc -V# out:rustc 1.53.0 (53cb7b09b 2021-06-17)
cargo -V
Cargo
# 进入项目
cargo build # 构建
cargo run # 执行
在线的IDE
Rust In IDEA
-
安装 Rust
有点慢 -
重启后,New Project,选择Rust
须按照上文了设置了默认工具链,新建项目才有显示rust版本1.44.1:
选择或不选择工具链、标准库
界面:
结构详情:
-
Cargo.toml
依赖管理。如:
[dependencies]
hyper = "0.12.35"
tokio-core = "0.1.17"
futures = "0.1.29"
如果不引入依赖,则会报错找不到类。
Hello, world!
向main.rs
拷入代码:
fn main() {
const X: i32 = 9;
println!("{}", "Hello, world!".to_owned() + &X.to_string());
}
点绿色三角执行,执行结果:
Hello, world!9
有什么感想?比如说,类型是不是比较严格?——Java、Js用+号就可以连接两个对象了
- exe运行
Cargo项目,进入target/debug目录找到可执行文件,比如
.\rustTestFourth.exe
注意是.\
Rust In VsCode
辅助
依赖镜像 若引入了外部依赖,需要下载,则设置从镜像库下载
找到磁盘上的.cargo
目录,新建文件名称config
,填入下述内容:
[source.crates-io]
replace-with = 'tuna'
[source.tuna]
registry = "https://mirrors.tuna.tsinghua.edu.cn/git/crates.io-index.git"
如果起效了,会下载本地磁盘不存在的包,如图:
语法
引用别的类及函数
- code
// main.rs
use second::Pear;
fn main() {
let obj = Pear::new(511, String::from("yellow"));
obj.color();
}
// second.rs
pub struct Pear {
size: i32,
color: String,
}
impl Pear {
pub fn new(size_value: i32, color_value: String) -> Pear {
Pear {
size: size_value,
color: color_value
}
}
pub fn color(&self) {
println!("Its color is {}", self.color);
self.size();
}
fn size(&self) {
println!("It's large {}", self.size);
}
}
- output
Its color is yellow
It's large 511
线程
- code
Cargo.toml
[dependencies]
chrono = { version = “0.4”, features = [“serde”] }
use std::thread;
use std::time::{Duration, SystemTime};
use chrono::{DateTime, Local, NaiveDateTime};
pub mod constant{
pub fn get_number() -> u64 {
2
}
}
fn spawn_fn() {
for i in 0..4 {
println!("spawn {}-{}", i, Local::now().naive_local());
thread::sleep(Duration::from_millis(constant::get_number())); // constant::get_number() 不要漏了括弧
}
}
fn main() {
thread::spawn(spawn_fn);
for i in 1..5 { // 1-4 循环
println!("main {}-{}", i, Local::now().naive_local());
thread::sleep(Duration::from_millis(constant::get_number()));
}
}
- output👇
main 1-2021-01-08 22:38:07.104416800
spawn 0-2021-01-08 22:38:07.104574500
main 2-2021-01-08 22:38:07.112333
spawn 1-2021-01-08 22:38:07.112351100
main 3-2021-01-08 22:38:07.115331800
spawn 2-2021-01-08 22:38:07.115616700
main 4-2021-01-08 22:38:07.118316
spawn 3-2021-01-08 22:38:07.118338
泛型
- code
struct Point<T> { // 定义结构体的属性为泛型
x: T,
y: T,
}
impl<T> Point<T> {
fn x(&self) -> &T { // 返回属性之一
&self.x
}
}
fn main() {
let p = Point { x: 33.19, y: 75.28 };
println!("p.x = {}", p.x);
println!("p.x() = {}", p.x());
println!("p.y = {}", p.y);
}
- output
p.x = 33.19
p.x() = 33.19
p.y = 75.28
- code
结构体
一
- code
fn main() {
#[derive(Debug)]
struct employee {
name: String,
age: u8,
isNative: bool,
}
let name = String::from("包惜弱");
let isNative = false;
let epl = employee {
name,
age: 17,
isNative,
};
println!("这个雇员的信息:{:?}", epl);
}
- output
这个雇员的信息:employee { name: "包惜弱", age: 17, isNative: false }
二
- code
struct User {
username: String,
email: String,
sign_in_count: u64,
active: bool,
}
fn main() {
let mut lord = User {
email: String::from("VillagePeak@example.com"),
username: String::from("元始天尊"),
active: false,
sign_in_count: 9999,
};
let ha = User {
email: String::from("H@example.com"),
username: String::from("通天教主"),
..lord // 复制部分属性
};
println!("激活 == {}", ha.active);
println!("用户名 == {}", ha.username);
println!("数目 == {}", ha.sign_in_count);
lord.sign_in_count = 8848;
println!("数目 == {}", ha.sign_in_count);
}
- output
激活 == false
用户名 == 通天教主
数目 == 9999
数目 == 9999
元组结构体
- code
fn main() {
// 矩形
struct square(u32, u32, u32, u32);
// 三角形
struct triangle(u32, u32, u32);
let square1 = square(2, 3, 2, 3);
let triangle1 = triangle(4, 4, 4);
println!("{},{},{},{}", square1.0, square1.1, square1.2, square1.3);
println!("{},{},{}", triangle1.0, triangle1.1, triangle1.2);
}
- output
2,3,2,3
4,4,4
模块 访问控制
- code
pub mod custom_{ // 定义模块 开放
// pub fn max(array: &[T]) -> T {
pub fn max(array: &[i32]) -> i32 { // pub开放max函数
let mut max_index = 0;
let mut i = 1;
while i < array.len() {
if array[i] > array[max_index] {
max_index = i;
println!("较大值索引是{}", i)
}
i += 1;
}
array[max_index]
}
}
fn main() {
let a = [9527, 27, 10010, 6, 3, 6751];
println!("max = {}", custom_::max(&a)); // 模块::公共函数 调用
}
- output
较大值索引是2
max = 10010
Trait 特性
所有权 指针那些事儿
- 说明
所有者:值的所有者就是变量
字符串 有没浅度拷贝、深度拷贝?
- code
fn main() {
let name1 = String::from("Zhenyuan");
let name2 = name1;
println!("{}", name1)
}
- 编译报错👇
error[E0382]: borrow of moved value: `name1`
--> src\main.rs:27:20
|
25 | let name1 = String::from("Zhenyuan");
| ----- move occurs because `name1` has type `std::string::String`, which does not implement the `Copy` trait
26 | let name2 = name1;
| ----- value moved here
27 | println!("{}", name1)
| ^^^^^ value borrowed here after move
error: aborting due to previous error; 1 warning emitted
报错原因说得很详细了,因为String没实现拷贝特性,已经移动,值已经被租了,name1已经到期了。但可以克隆值,保证所有权不变,见下文↓。
3) 值拷贝的例子↓,以下代码不报错
fn main() {
let x1 = 9;
let x2 = x1;
println!("{}", x1)
}
fn main() {
let s1 = "龙";
let s2 = s1;
println!("{}", s1)
}
// 或者使用克隆
fn main() {
let s1 = String::from("龙威");
let s2 = s1.clone();
println!("{}", s1)
}
引用 不释放所有权
- code
- output
奋斗
学习指导
网站
执行rustup
命令:rustup doc --book
,打开web页面,可获得匹配当前rust版本的文档,保证例子可以跑起来。
Getting Started
老规矩,Hello Everyone !
- 代码
fn main() {
// let x = 5;
let x = "9";
println!("{}", "Hello, world!".to_owned() + x);
}
- 疑问1:为什么字符串连接要用到函数
to_owned
?
答:语法使然 - 疑问2:为什么连接个字符串,打印时,还要加
{}
进行格式化?
小实践
简单功能
简单的线程
代码:
use std::thread;
use std::time::Duration;
fn main() {
thread::spawn(|| {
for i in 1..10 {
println!("hi number {} from the spawned thread!", i);
thread::sleep(Duration::from_millis(1));
}
});
for i in 1..5 {
println!("hi main number {} from the main thread!", i);
thread::sleep(Duration::from_millis(1));
}
}
控制台输出:
简单的接口调用:
在Cargo.toml加入对应依赖:
[dependencies]
hyper = "0.12.35"
tokio-core = "0.1.17"
futures = "0.1.29"
代码:
extern crate futures;
extern crate hyper;
extern crate tokio_core;
use futures::Future;
use hyper::{Client, Uri};
use tokio_core::reactor::Core;
fn main() {
// Core is the Tokio event loop used for making a non-blocking request
let mut core = Core::new().unwrap();
let client = Client::new();
let url: Uri = "http://kunpeng.csdn.net/ad/474".parse().unwrap();
assert_eq!(url.query(), None);
let _request_result = core.run(client
.get(url)
.map(|res| {
println!("Response: {}", res.status());
println!("Response: {:?}", res.body());
})
.map_err(|err| {
println!("Error: {}", err);
})
);
}
响应:
Body流需要转成明文。
读取简单的文本文件
在Cargo.toml加入对应依赖:
[dependencies]
hyper = "0.12.35"
tokio-core = "0.1.17"
futures = "0.1.29"
代码:
fn main() {
// / Create a path to the desired file
let path = Path::new("C:\\dev\\test\\project\\backend\\rust\\rustTestFourth\\src\\One.txt");
let display = path.display();
// Open the path in read-only mode, returns `io::Result<File>`
let mut file = match File::open(&path) {
// The `description` method of `io::Error` returns a string that
// describes the error
Err(why) => panic!("couldn't open {}: {}", display,
why.description()),
Ok(file) => file,
};
// Read the file contents into a string, returns `io::Result<usize>`
let mut s = String::new();
match file.read_to_string(&mut s) {
Err(why) => panic!("couldn't read {}: {}", display,
why.description()),
Ok(_) => print!("{} contains:\\n{}", display, s),
}
// `file` goes out of scope, and the "hello.txt" file gets closed
}
控制台输出响应,该响应是文件的具体内容。
打印控制台的输入
use std::io;
fn main() {
println!("Guess the number!");
println!("Please input your guess.");
let mut guess = String::new();
io::stdin()
.read_line(&mut guess)
.expect("Failed to read line");
println!("You guessed: {}", guess);
}
引入依赖库
- 引入依赖*
[dependencies]
ferris-says = "0.1"
- 主代码-打印Logo
use std::io::{BufWriter, stdin, stdout};
use ferris_says::say;
fn main() {
println!("I'm cc");
println!("Movie Starting");
let standout = stdout();
let message = String::from("TV Play");
// 获取msg的宽度
let mut buf = BufWriter::new(standout.lock());
say(message.as_bytes(), message.chars().count(), &mut buf); // 播放小电影
println!("打印的{}", message); // 比say早输出
}
注意standout是点不是括弧
- 编译,引入新包后,编译时下载:
- 执行结果:
猜数字游戏
fn recIn(correctlyMsg: i32) {
let mut msg = String::new();
let inIn = io::stdin()
.read_line(&mut msg)
.expect("Fmt failed");
let inNum: i32 = msg.trim().parse::<i32>().unwrap();
if (inNum == correctlyMsg) { // todo 改成Switch
println!("Your answer is correctly {}", msg)
} else {
let mut ret = String::new();
if inNum > correctlyMsg { // todo rust的三目运算符则搞?
ret = "bigger".to_string();
} else {
ret = "smaller".to_string();
}
println!("Sorry.Wrong.Your input is {} {}", ret, msg);
recIn(correctlyMsg);
}
}
fn main() {
println!("Come to one Game");
println!("Please input your answer,it's one number");
let msg2 = 32;
recIn(msg2);
return;
}
猜数字游戏2
- 引入依赖,随机数
[dependencies]
rand = "0.6.0"
下载依赖,好像下载了不少包:
- 主代码
use std::io;
use rand::Rng;
fn main() {
println!("Hello, world!");
let num = rand::thread_rng().gen_range(500, 505); // 随机数
println!("Please input one number");
let mut msg = String::new();
io::stdin()
.read_line(&mut msg)
.expect("Failed");
println!("Your input is {}", msg);
println!("Correctly number is {}", num);
}
还是同样,使用stdin标准输入,接收控制台输入并与变量的指针关联,这样才可打印正确。
猜数字游戏3
- 这次升级了,代码优雅了点:
use std::io;
use std::cmp::Ordering;
use rand::Rng;
use rand::seq::index::IndexVec::U32;
fn main() {
println!("Hello, world!");
let right:String = rand::thread_rng().gen_range(500, 505).to_string(); // 随机数
println!("Please input one number");
let mut guess = String::new();
io::stdin()
.read_line(&mut guess)
.expect("Failed");
println!("Your guess is {}", guess);
match guess.trim().cmp(&right) {
Ordering::Less => println!("太小"),
Ordering::Greater => println!("太大"),
Ordering::Equal => println!("胜利"),
};
println!("Correctly number is {}", right);
}
使用工具use std::cmp::Ordering;进行大小比较操作,那这个例子字符串和数字怎么比呀,我改成了字符串和字符串比,实验了一下也能行
猜数字游戏4 强转 循环
fn main() {
let secretNumber: u32 = 35;
loop {
let mut num1: String = String::new();
io::stdin().read_line(&mut num1).expect("异常");
// let num1: u32 = num1.trim().parse().expect("强转失败");
let num1: u32 = match num1.trim().parse(){
Ok(num) => num,
Err(_) => continue
};
println!("Please input your number");
match num1.cmp(&secretNumber) {
Ordering::Less => {
println!("Too small");
continue;
}
Ordering::Greater => {
println!("Too Large");
continue;
}
Ordering::Equal => {
println!("Success");
println!("Your number is {}", num1);
break;
}
}
}
}
实现接口
//结构体 实现接口
pub mod kongfu_background {
// 演武场
pub struct Box {
// 打拳
size: String,
power: String,
pub name: String,
}
// 实现
impl Box {
pub fn punches(name: &str) -> Box { // pub 公开函数
Box {
size: String::from("Long"),
power: String::from("75%"),
name: String::from(name),
}
}
}
}
fn main() {
let mut box1 = kongfu_background::Box::punches("x"); // 注意加分号
println!("{}", box1.name);
box1.name = String::from("形意拳");
println!("{}", box1.name)
}