learn rust, 40+ demos
std:
:Result<_, _>
cannot be formatted with the default formatterEmployee
cannot be formatted with the default formatternot found in this scope
pub fn arg_result(arg: String) -> tuple {
| ^^^^^ not found in this scope
error: aborting due to previous error
// use
let ab = utils::arg_result(arg);
println!("arg result==?,{}", ab);
println!("{:?}", arg);
// var utils.rs
pub fn arg_result(arg: String) -> tuple {
// return ("a", "2");
("a","b")
}
Use of moved value
returns a value referencing data owned by the current function
查看例子lifecycle/lifecycle.rs
cannot return value referencing local variable "temp_arg"
explicit lifetime required in the type of
rust 是静态类型,必须知道类型,且不能随更改类型
变量隐藏和复写
fn main(){
let x =5;
let x=x+1;
let x =x*2;
}
倒数第二及以前的段落必须结尾加分号
函数内部 最后一行如果不用return 的方式返回,就不能给该行使用分号
// 如果函数最后一行不带return
且不带分号,则认为是一个return
,可省去关键字return
fn five()->i32{
5
}
## 疑问
### 1. 如何if == string?
### 2. while循环和for循环的区别:
> 如果数组的索引长度在运行时增加,那么while循环显示错误,但在for循环的情况下不会发生这种情况。 因此,可以说for循环增加了代码的安全性并消除了错误的可能性。
### 3. 为什么要加!
### 4. 使用前,需要将变量声明,不存在js类似的变量提升
### 5. i32表示多少
### 6. 不能打印长元组?? 报错,WHY?
```rust
fn main(){
let too_long_tuple=(1,65,56,6,565,65,95,5,655,656,64,65,5,61,6,5656);
println!("too long tuple:{:?}",too_long_tuple);
}
/*
* @pair 入参一个,内含两个元素,数据类型为(i32,bool)元组
* @return 返回值为 数据类型为,也是个元组 (bool,i32)
*/
fn reverse(pair:(i32,bool))->(bool,i32){
let (integer,boolean)=pair;
(boolean,integer)
}
fn main(){
let pair = (11,true);
println!("{:?}",reverse(pair));
}
fn main(){
println!("{}",fool(999));
}
fn fool(num:i32)->(i32){
return num+999; // 或者num+999,不需要return
}
答案:表示引用
use std::mem;
fn analyze_slice(slice:&[i32]){
println!("第一个元素:{}",slice[0]);
println!("数组的长度:{}",slice.len());
}
fn main(){
let xs:[i32;5]=[9898,9856,685659,66,9];
analyze_slice(&xs)//为什么要加一个&呢?
}
- match 由分支(arms)构成,一个分支包含一个模式(pattern)
- match的cmp方法会返回`Ordering:Greater`,`Ordering:Less`,`Ordering:Equal`
fn inspect(event:WebEvent){
// match干嘛的?
match event {
WebEvent::PageLoad=>println!("page load"),
WebEvent::PageUnload=>println!("page unload"),
WebEvent::Keypress(c)=>println!("pressed '{}'.",c),
WebEvent::Paste(s)=>println!("pasted\"{}\".",s),
WebEvent::Click {x,y}=>println!("click at x={},y={}",x,y)
}
}
enum Point{
x = 111
}
println!("{}");
- Result 风格,大写Ok,因为它是一个枚举enum
- future中,使用小写ok方法【首选】
let num:u32=guess.trim().parse().expect('xxx')
io::stdin().read_line(&mut xx).expect(“错误~~”) ,存到一个变量
fn main(){
let long_tuple =(
1u8,2u16,3u32,4u64,
-1i8,-2i16,-3i32,-4i64,
0.1f32,0.2f64,'a',true);
}
?
这个后面的问号是干嘛的?
use actix_web::{web, App, HttpResponse, HttpServer};
#[actix_rt::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new().route("/", web::get().to(|| HttpResponse::Ok()))
})
.bind("127.0.0.1:8088")? //What is that ?
.run()
.await
}
use of moved value
可以:utils::arg_result(arg.clone())解决问题
impl
impl
作为关键字定义参数类型impl
关键字定义指定struct的实现代码,然后在这代码块中定义与struct相关的方法方法与函数非常相似
Struct
,且第一个参数是self
impl Style {
fn area(&self) -> u32 {
self.width * self.height
}
}
fn main() {
let rect = Style {
width: 30,
height: 90,
};
println!(“{:?}”, rect.area())
}
### 26 文件调用别的文件的函数方法
```rust
// a.rs
use crate::shared::QRErrorCorrectLevel::H;
// b.rs
pub struct Code {
width: i32,
height: i32,
type_number: i32,
color_dark: String,
color_light: String,
correct_level: H,
}
// main.rs
mod shared;
use bytes::{Bytes}
fn main(){
let b = Bytes::new();
println("{:?}",&b[..])
}
看起来 bytes,声明是 b””, 需要 &x[..]
展开,然后是是一个数组
两种引用类型:
&
&mut
规则:
Rust 会通过分析引用对象的声明周期
来防止引用一个不可用的对象。
生命周期的主要目标是为了防止悬空指针
{
let r;
{
let x =5;
r = &x; // 被销毁了
}
println!("r :{}",r)
}
外部作用域声明了变量r
,内部作用域声明了变量x
,在内部产生设置了r
为 x
的引用,当内部区域终止时,尝试打印r
,上述代码无法通过编译。
// error
pub fn arg_array(arg:String) -> &mut [T] {
["a"]
}
// 其中一种方法
pub fn arg_array(arg: String) -> Vec<&'static str> {
println!("入参=>{}", arg);
let array = ["das", "das","dsad"];
println!("len =>{}",array.len());
for i in 0..array.len(){
vec.push(array[i])
}
return vec;
}
struct MainModule {
user: String,
// TODO auto 1 2 3 4 5 6
worker_processes: u32,
event: EventModule,
// error_log: String,
// pid: String,
// worker_rlimit_nofile: u32,
// http: HttpModule,
}
struct EventModule {
worker_connections: u32,
}
fn main(){
let config = MainModule {
user: String::from("www www"),
worker_processes: 2
};
println!("==>{:#?}", config.event) // why can;t print this?
}
fn main() {
let object = json_to_struct();
println!("{:#?}", object) // TestStruct` cannot be formatted using `{:?}`
}
fn json_to_struct() -> Result<()> {
let json = r#"
{
"name":"asjdsak",
"age":30,
"type":true
}
"#;
let v: Value = serde_json::from_str(json)?;
println!("==>{:?}", v);
Ok(())
// TODO 如何返回v
}
改动如下:
use serde_json::{Result,Value};
fn main() {
let object = json_to_struct();
println!("{:#?}", object) // TestStruct` cannot be formatted using `{:?}`
}
fn json_to_struct() -> Result<Value> {
let json = r#"
{
"name":"asjdsak",
"age":30,
"type":true
}
"#;
let v: Value = serde_json::from_str(json)?;
println!("==>{:?}", v);
Ok(v)
}
二次改动
use serde_json::{Result,Value};
fn main() {
let object = json_to_struct().unwrap();
println!("{:#?}", object); // TestStruct` cannot be formatted using `{:?}`
// println!("{:#?}", object) // TestStruct` cannot be formatted using `{:?}`
// println!("name==>{:#?}", object.name);
println!("=dsadd=>{}", object["name"]);
}
fn json_to_struct() ->Result<Value> {
let json = r#"
{
"name":"asjdsak",
"age":30,
"type":true
}
"#;
let v: Value = serde_json::from_str(json)?;
println!("name===>{}",v["name"]);
println!("==>{:?}", v);
Ok(v)
}
extern crate rustc_serialize;
use rustc_serialize::json;
#[derive(RustcDecodable, RustcEncodable)]
#[derive(Debug)]
struct Profile {
name: String,
age: u8,
phones: Vec<String>,
}
fn main() {
let json_str = r#"
{
"name":"veaba",
"age":26,
"phones":[
"110",
"120",
"119"
]
}
"#;
let profile: Profile = json::decode(&json_str).unwrap();
println!("json to struct==>{:#?}", profile);
}
extern crate rustc_serialize;
use rustc_serialize::json;
#[derive(RustcDecodable, RustcEncodable)]
#[derive(Debug)]
struct Profile {
name: String,
age: u8,
phones: Vec<String>,
}
fn main() {
let profile = Profile {
name: "Jobs".to_string(),
age: 99,
// phones: vec!["110", "120", "199", "144"],
phones: vec!["110".to_string(), "120".to_string(), "199".to_string(), "144".to_string()],
};
let encode = json::encode(&profile).unwrap();
println!("struct to json==>{}", encode);
}
#[derive(Debug)]
,否则无法使用 {:#?}打印struct
extern crate rustc_serialize;
use rustc_serialize::json;
// Struct Parent
#[derive(RustcDecodable, RustcEncodable)]
#[derive(Debug)]
struct Parent {
name: String,
age: u8,
children: Children,
}
// Struct Children
#[derive(RustcDecodable, RustcEncodable)]
#[derive(Debug)]
struct Children {
name: String,
age: u8,
school: String,
}
fn main() {
let person = Parent {
name: "Li".to_string(),
age: 35,
children: Children {
name: "Li's son".to_string(),
age: 8,
school: "primary".to_string(),
},
};
println!("no children==>{:#?}", person); // 可以打印出来person
let to_json_str = json::encode(&person).unwrap();
println!("json str==>{}", to_json_str);
}
也只能参考struct 转 json 字符串
[allow(dead_code)]
Rust 使用闭包(closure
) 来创建匿名函数
let num=5;
let plus_num= |x:i32| x +num;
闭包plus_num
借用了它的作用域中的let
绑定num
,如想让闭包获取所有权,可以使用move
关键字:
let mut num=5;
{
let mut add_num=move |x:i32| num+=x; // 闭包通过move 获取num所有权
add_num(5)
}
fn get_merge_config() {
let default_config = get_default_config();
let outside_config= get_outside_config();
let merge_config=ConfigModule{
default_config, // TODO ??
..outside_config
};
println!("default config===>{:#?}", default_config);
return merge_config;
}
// TODO 如何简写一下代码?
fn main() {
let a = String::from("aa");
let b = String::from("bb");
// let c: String = a | b;
let c;
if a.len() > 0 {
c = a
} else {
c = b
}
println!("{}", c);
}
rust 通过自定义类型主要通过以下两个关键形成:
常量可以通过const
static
关键字声明
- const x = 99; 不合适。x推荐大写
- const X=8;错误,X虽然大写,但需要声明数据类型
- const X:u32=999 √
- const mut X:u32=99 常量不接受可变量修饰符
结构:
rust 的结构和解构
struct Pair(i32,f32);
struct Person<'a> {
name: &'a str,
//这是啥子?
age: u8,
}
fn main(){
let pair =Pair(99,99.9);
let Pair{x,y}=pair; //todo ??
println!("{:?}\n{:?}",x,y);
let name = "Jogel";
let age = 27;
let jogel = Person { name, age };
println!("{:?}",jogel);
}
如何跨文件使用use
```rust
enum Status{
Rich,
Poor
}
enum Work{
Google,
Microsoft,
}
use Status::{Poor,Rich};
use Work::*;
## 定时器
```rust
use std::thread;
use std::time::Duration;
fn main() {
let mut x = 1;
while x < 10 {
println!("{},{}",x,"哈哈哈哈");
x += 1;
thread::sleep(Duration::from_millis(1000));
}
println!("{},{}",x,"哦哦哦");
}
;
堆栈存储器
后进先出
,进电梯 原则堆栈内存
有组织的内存,比堆内存
更快堆内存
用于存储内容堆内存
堆内存
是有组织的内存 堆内存
中找到一个空的空格并返回一个指针,这叫 在对上分配
;
;
v1
向量分配给向量v2
v1
、v2
都超出范围时,两者都会尝试释放内存;
v1
向量不再有效v1
超出范围时,它不需要释放v1
的内存;
fn main(){
let v1= vec![1,2,3,"666"];
let v2 = v2;
}
u32
bool
:true
, false
f64
char
编译器在编译时会根据一系列的规则进行检查,runtime,ownership 所有权系统的任何功能不会减慢程序
Heap(堆):程序运行时产生,用户去申请的,存储值
Stack(栈):push、pop 等相关,函数运行时而临时占用的内存区域。后进先出(叠盘子)
访问堆上的数据比访问栈上的数据慢,因为必须通过指针来访问
调用函数,传递函数的值(可能是堆上数据的指针)和函数局部变量被压入栈中,当函数结束时,这些值被移除栈。
rust的所有权操作,属于新的概念。
name | desc | |
---|---|---|
.rs | rust文件后缀 | |
Cargo.lock | ||
Cargo.toml | ||
xxx.iml | ||
src目录 | 源码 | |
target目录 | ||
mnt i | i是可以更改变量,可变变量 | |
双引号 | 给字符/对象 | |
str | String::from(“a string”) | |
char | a ,单引号是一个单字符,超出则编译错误 let char = 'a' |
|
&str | abd ,双引号括住是多个字符 let a="你好" |
|
return None | ||
return true | ||
return false | ||
return Err(err) | ||
impl | ||
符号整数 | i开头 | |
无符号整数 | u开头,不是负号 | |
#[derive(Debug)] | ||
#[allow(dead_code)] | ||
{:?} | 打印数组、元组 | |
match | rust关键字提供匹配模式,类似C的 switch |
参考https://doc.rust-lang.org/rust-by-example/flow_control/match.html |
_ | 下划线 | _=>print!(“xx”),类似如果下划线在match中,类似switch 的default: |
let mut foo = String::new()
new 是String类型的关联函数,针对类型实现的,常称:静态方法new
创建类型实例的惯用函数名ok
,Err
。return
的是一个 输入的字节数usize
rand
cratestd:
:Ordering
类型,Ordering
也是一个枚举,成员是Less
(小于),Greater
(大于),Equal
(等于),比较两个值的三种结果}
Google,
Microsoft,
Alibaba=999
- rust 使用 snake case 风格,所有字母都小写并使用下划线分割
- rust 函数声明提升,无论声明在调用之前或之后
- rust 函数的参数必须有类型fn test(arg1:i32,arg2:u64)
- rust 是一门基于表达式的语言(expression-based)
- rust 无法使用`x=y=6`
### 常量和变量的区别
- let 变量
- let x =6 不可变的变量
- let mut x=6 自动推断类型,且可变
- const 常量,大写
- const x = 99; 不合适。x推荐大写
- const X=8;错误,X虽然大写,但需要声明数据类型
- const mut X:u32=99 常量不接受可变量修饰符
- const X:u32=999 √
### 隐藏,shadowing
重复声明的方式来达到变量替换的目的,后者会替换前面的变量
```rust
fn main(){
let mut x = 666;
let x =999;
let mut x = 888;//此处的mut 是多余了
}
rustc —version
update 更新
rustup update
uninstall 下载
rustup self uninstall
处理一次猜测
```rust
use std::io;
fn main(){
println!(“hello world”);
let mut guess =String::new(); //?干嘛的,空字符串
println!(“请输入:{}”,guess);
io::stdin().read_line(&mut guess)
.expect("读取行失败");
println!(“你猜的,{}”,guess);
}
### 猜到对数字
```toml
[package]
name = "learn-rust"
version = "0.1.0"
authors = ["veaba"]
edition = "2018"
[dependencies]
rand="0.3.14"
/**
@desc 步骤分析:
1、生成一个1-100的随机数
2、键盘输入一值
3、loop循环
4、比较大小
*/
use std::io;
use rand::Rng;
use std::cmp::{Ordering,Ord};
fn main() {
let code = rand::thread_rng().gen_range(1,101);
println!("code:{}",code);
loop {
println!("======== 请输入你的字符 ========");
let mut key=String::new();//生成一个类型为String的实例
io::stdin().read_line(&mut key)
.expect("输入错误~");
println!("你输入的:{}",key);
// rust 允许用一个新值来隐藏(shadow)guess之前的值:常用于转换值类型之类的场景,
// 这种用法,允许复用guess便利店个名称,而不是创建两个不同的变量
// 详见:https://kaisery.github.io/trpl-zh-cn/ch03-00-common-programming-concepts.html
let key:u32=match key.trim().parse(){
Ok(num)=>num,
Err(_)=>{
println!("字符类型不对");
continue
}
};
// key 和code 没办法对比,请改为CMP->cmp
match key.CMP(&code) {
Ordering::Less=>println!("太小了"),
Ordering::Greater=>println!("太大了"),
Ordering::Equal=>{
println!("猜中了,biubiu");
break;
}
}
}
}
fn main(){
print!("Hello,world!");
}
执行命令
rustc hello.rs
会生成hello.exe
、hello.pdb
,windows 下运行hello.exe才会运行
函数 | 解释 | demo |
---|---|---|
format!() | 格式化文本写入字符串 | |
print! | 类似format!,但打印到控制台 | |
println!()类似print!但会添加新的一行 | ||
eprint! | 类型format!,打印为标准错误 | |
eprintln!()类似eprint,但会添加新的一行 | ||
// ->指返回
fn add_one(x:i32)->i32{
x+1
}
// todo 问号是干嘛的?fs::write("foo.txt","哈哈哈")?;
// let _ = fs::write("foo.txt", "哈哈哈");
fn main(){
let a=9;
if a==9 {
print!("aaa");
}
}
println!("{}","xxx");
println!("{:?}",xxx);
switch
fn main(){
let number=1;
println!("the number:{}",number);
// prime
match number {
1=>println!("One"),
2=>println!("Two"),
3|4|5|6|7|11=>println!("匹配的数字"),
12...19=>println!("A ten哇"),
// 不是特殊的
_=>println!("default"),
}
let boolean =true;
let binary =match boolean
{
false=>0,
true=>1
};
println!("{}-{}",boolean,binary);
}
fn main(){
let a=9;
if a==8 {
println!("aaa");
}
else if a>8 {
println!("bbb");
}
else{
println!("ccc");
}
}
expected integer, found char
too many characters in char literal 表示只能是单个字符!!a或者b,不能ab
String::from(“S/\q\t\nI}POYY
?M>NM>M<JKLKL:KLII/\dh”) \d这里有问题
}
println!("{}",i);
if i==10{
break
}
i+=1
### for循环
- 循环数组
```rust
// 循环数组
fn main(){
let res =["mango","apple","banana","litchi","watermelon"];
for i in res.iter() { //iter()方法
println!("{}",i)
}
}
//TODO 循环对象
fn main(){
let mut i=0;
while i<=10 {
println!("{}",i);
i+=1
}
}
rust 有两种主要的字符串类型 &str
和String
&str
字符串片段(string slices)&'static str
字符串常量
// &'static str 的返回值
fn main(){
println!("一个函数返回一个字符串:{}",return_a_string());
}
fn return_a_string()->(&'static str){
let str = "哇哈哈哈";
return str
}
a被回收,编译直接报错
//
fn main(){
let a =20;
let b = a;
println!("{}",a)
}
但是 下面这样就不会被回收~~ TODO ?why?
fn main1(){
let a =20;
let b = a;
println!("{}",b);
println!("{}",a)
}
fn main(){
let s =String::from("SDUSAJDOISAJ IUJODSJAI ");//啥意思?
take_ownership(s);
let ch ='a';
move_copy(ch);
println!("main:{}",ch)
}
fn take_ownership(str:String){
println!("take_ownership:{}",str)
}
fn move_copy(c:char){
println!("move_copy:{}",c)
}
```rust
fn main(){
let ch = ‘a’;
//let tt = ‘abad’;//为啥这里会报错,因为char 类型只能是一个字符
move_copy(ch);
move_copy(tt);
}
fn move_copy(str:String){
println!(“{}”,str)
}
### 存放任意字符,斜杠之类的
> \d \q都有问题
>let s =String::from("S/\q\t\nI}POYY<M?>?M>NM>M<JKLKL:KLII//\dh");
## 字符串函数/方法
### len() 取长度
```rust
fn main(){
let x = 999;
println!("{}",x.len()); //错误
let y ="66";
println!("{}",y.len());
}
fn main(){
let str1 = "\n 444";
println!("{}",str1.trim());
}
use std::fs;
fn write_file() -> std::io::Result<()> {
fs::write("foo.txt","哈哈哈")?;
Ok(())
}
fn main() {
println!("hello world");
let _ = write_file();
}
类型 | 值 |
---|---|
布尔类型 | true false |
字符类型 | 单个Unicode类型,存储4个字节 |
数值类型-符号整数 | i8 i16 i32 i64 isize |
数值类型-无符号整数 | u8 u16 u32 u64 usize |
数值类型-浮点数 | f32 f64 |
字符串类型-底层不定长类型 | str |
字符串类型-字符串切片 | &str ,静态分配,固定大小,不可变 |
字符串类型-堆分配字符串 | String ,可变 |
数组 | 固定大小,且元素都同类型,[T;N] |
切片 | 引用一个数组的部分数据,并且不需要拷贝,&[T] |
元组 | 固定大小的有序列表,元素都有自己的类型,通过解构或者索引来获取值 |
指针 | 最底层的裸指针,*const T *mut T ,但解引用它们是不安全的,必须放到unsafe 块里 |
函数 | 具有函数类型的变量实质上是一个函数指针 |
元类型 | 即() ,其唯一值也是() |
整型
。没有小数部分的数字,默认i32
rust中的整型
长度 | 有符号 | 无符号(负数) | -(2n-1 -1) |
---|---|---|---|
8-bit | i8 |
u8 |
|
16-bit | i16 |
u16 |
|
32-bit | i32 |
u32 |
|
64-bit | i64 |
u64 |
|
arch | isize |
usize |
|
isize
和usize
类型依赖计算机架构,64位是64位,32位是32位
rust中的整型字面值
数字字面值 | 例子 |
---|---|
Decimal |
98_222 |
Hex |
0xff |
Octal |
0o77 |
Binary |
0b1111_0000 |
byte (u8 only) |
bA |
整型溢出:u8
放到0-255值,修改为256
,被称为整型溢出
(idnteger overflow)
在 release 构建中,Rust 不检测溢出,相反会进行一种被称为 “two’s complement wrapping” 的操作。简而言之,256 变成 0,257 变成 1,依此类推。依赖溢出被认为是一种错误,即便可能出现这种行为。如果你确实需要这种行为,标准库中有一个类型显式提供此功能,Wrapping。
浮点型
。带小数点的数字,有两个原生的浮点数类型f32
、f64
,默认f64
。IEEE-754标准f32
单精度浮点数f64
双精度浮点数}
- `布尔型`。bool
- true
- false
- `字符类`。
- `char`代表Unicode,单个字符,中文或者其他语言的单字
### 复合类型
- tuple `(a,b,c,d)`
- array `[a,b,c,d]`
### 基本类型
|类型|最小值|最大值|值|描述|所属组|
|---|---|---|---|---|---|
|array||||1||
|bool||||||
|char||||||
|f32||||||
|f64||||||
|fn||||||
|i8||||||
|i16||||||
|i32||||||
|i64||||||
|i128||||||
|isize||||||
|never||||||
|pointer||||||
|reference||||||
|slice||||||
|str||||||
|tuple||||||
|u8||||||
|u16||||||
|u32||||||
|u64||||||
|u128||||||
|unit||||||
|usize||||||
> https://doc.rust-lang.org/nightly/std/primitive.i8.html
### 数字转为其他类型
## rustup
Command | Description
----------------------------------------------------------- | ------------------------------------------------------------
`rustup default nightly` | Set the default toolchain to the latest nightly
`rustup target list` | List all available targets for the active toolchain
`rustup target add arm-linux-androideabi` | Install the Android target
`rustup target remove arm-linux-androideabi` | Remove the Android target
`rustup run nightly rustc foo.rs` | Run the nightly regardless of the active toolchain
`rustc +nightly foo.rs` | Shorthand way to run a nightly compiler
`rustup run nightly bash` | Run a shell configured for the nightly compiler
`rustup default stable-msvc` | On Windows, use the MSVC toolchain instead of GNU
`rustup override set nightly-2015-04-01` | For the current directory, use a nightly from a specific date
`rustup toolchain link my-toolchain "C:\RustInstallation"` | Install a custom toolchain by symlinking an existing installation
`rustup show` | Show which toolchain will be used in the current directory
`rustup toolchain uninstall nightly` | Uninstall a given toolchain
`rustup toolchain help` | Show the `help` page for a subcommand (like `toolchain`)
`rustup man cargo` | \(*Unix only*\) View the man page for a given command (like `cargo`)
## Cargo
- https://rustlang-cn.org/office/rust/cargo/getting-started/installation.html
### 安装Cargo
> curl https://sh.rustup.rs -sSf | sh
如果顺利则:
> Rust is installed now. Great!
### Cargo 第一步
创建项目:
> cargo new helloworld
build
>cargo build
运行
>./target/debug/helloworld
cargo run
>cargo run
cargo doc --open 生成并打开一个文档,构建所有本地依赖提供的文档。帅!
>cargo doc --open
### cargo 指南
为什么会有cargo:
- 引入两个带有各种程序包信息的元数据文件
- 获取和构建项目依赖
- 正确的构建参数调用rustc 和其他构建工具
- 引入惯例使得rust程序包开发管理更加容易
已存的cargo项目
```cmd
git clone xx
cd xx
cargo build
一个cargo依赖如何添加
[dependencies]
time="0.1.12"
cargo build 会获取新的依赖以及依赖的依赖,一并编译。并且更新Cargo.lock文件
cargo update 更新依赖
cargo 项目结构:
.
├── Cargo.lock 具体依赖信息,cargo维护,不应该手动修改,可防止.gitignore文件
├── Cargo.toml 广义上秒数项目的依赖文件,开发者编写
├── benches 性能评估
│ └── large-input.rs
├── examples 示例目录
│ └── simple.rs
├── src 源码
│ ├── bin
│ │ └── another_executable.rs
│ ├── lib.rs 库文件
│ └── main.rs 默认可执行文件源代码
└── tests 单元测试
└── some-integration-tests.rs
[package]
name = "hello_world"
version = "0.1.0"
authors = ["Your Name <you@example.com>"]
[dependencies]
# 指定依赖仓库
rand = { git = "https://github.com/rust-lang-nursery/rand.git" }
# 解决指定版本,没多卵用。
rand = { git = "https://github.com/rust-lang-nursery/rand.git", rev = "9f35b8e" }
cargo update 更新所有依赖
cargo update -p rand 仅更新rand
src
目录下每个文件中的 tests/
目录,单元测试test/
目录是集成风格的测试cargo test
会运行额外的检查参考文档https://doc.rust-lang.org/book/testing.html
可执行指定参数测试,将测试名称含有foo的所有测试
carto test foo
language:rust
rust:
- stable
- beta
- nightly
matrix:
allow_failures:
- rust :nightly
rust-nightly:
statge:build
image:rustlang/rust:nightly
script:
- cargo build --verbose
- cargo test --verbose
allow_failure:true
#### build.sr.ht
- 确保将`<your repo>`和`<your project>`改变为要克隆和已克隆的目录。
- 将会在stable和nightly通道测试和构建文档
- 但是任何nightly构建中断将不会使整体构建失败
- 参考builds.sr.ht documentation https://man.sr.ht/builds.sr.ht/
```yml
image: archlinux
packages:
- rustup
sources:
- <your repo>
tasks:
- setup: |
rustup toolchain install nightly stable
cd <your project>/
rustup run stable cargo fetch
- stable: |
rustup default stable
cd <your project>/
cargo build --verbose
cargo test --verbose
- nightly: |
rustup default nightly
cd <your project>/
cargo build --verbose ||:
cargo test --verbose ||:
- docs: |
cd <your project>/
rustup run stable cargo doc --no-deps
rustup run nightly cargo doc --no-deps ||:
[dependencies]
rand = { git = "https://github.com/rust-lang-nursery/rand" }
# 指定分支
[dependencies]
rand = { git = "https://github.com/rust-lang-nursery/rand", branch = "next" }
# 路径依赖指定
[dependencies]
hello_utils = { path = "hello_utils" }
# 发布cargo箱子
[dependencies]
hello_utils = { path = "hello_utils", version = "0.1.0" }
Blocking waiting for file lock on the registry index
解决: rm -rf ~/.cargo/registry/index/*