V1.33.0 RFC -> nightly -> beta -> stable
主版本号:API不兼容修改
次版本号:向下兼容功能新增
修订号:向下兼容问题修正
国内源:
export RUSTUP_DIST_SERVER=https://mirrors.ustc.edu.cn/rust-static
export RUSTUP_UPDATE_ROOT=https://mirrors.ustc.edu.cn/rust-static/rustup
# $HOME/.cargo/config
[source.crates-io]
registry = "https://github.com/rust-lang/crates.io-index"
replace-with = 'ustc'
[source.ustc]
registry = "git://mirrors.ustc.edu.cn/crates.io-index"
use std::prelude::*;
将常用的std库内容导入。
Format 格式:
let variable:i32 = 100;
let mut x = 5;
let (mut a, mut b) = (1,2);
// let _ = 10; // _ 合法,但是不能单独使用
let是一个模式解构,mut x
是一个组合/模式。
let x =10;
// x = 20; // error
let x = "abc"; // ok, 必须有let, x被重定义了
let s:Vec<_> = call_fuc();
不清楚s存储的内容,但是通过call_fuc()返回值编译器自己推导。
type Age = u32
Age与u32等价。
静态变量static GL:i32 = 0;
可变全局变量读写都必须使用unsafe修饰。
在Rust中,如果用户需要使用比较复杂的全局变量初始化,推荐使用lazy_static库。
const修饰的常量可能会被优化,所以不要使用hack方式修改值,并且也无法使用let匹配。
let mut x = true;
let y = false;
x = !x; // 按位取反或者逻辑非,由数据类型决定
x = x && y; // 逻辑与
x = x & y; // 按位与
x = x || y; // 逻辑或
x = x | y; // 按位或
x = x^y; // 按位异或
let love = '❤'; // char 可以表达任何unicode字符,4字节
let c1 = '\n'; // 换行符
let c2 = '\x7f'; // 8 bit 字符变量
let c3 = '\u{7FFF}'; // unicode字符
let a1:u8 = b'A'; // 用来表示ascii字符
在Rust中,我们可以为任何一个类型添加方法,整型也不例外。
let x : i32 = 9;
println!("9 power 3 = {}", x.pow(3));
针对溢出问题:(u8整数溢出等)
默认情况下,在debug模式下编译器会自动插入整数溢出检查,一旦发生溢出,则会引发panic;
在release模式下,不检查整数溢出,而是采用自动舍弃高位的方式。
指针:
Box
指向类型T的,有所有权的指针,有权释放内存&T
指向类型T的借用指针,即引用,无权释放内存&mut T
指向类型T的mut借用指针,可以写数据,无权释放内存*const T
指向类型T的只读裸指针,无生命周期信息,不可写数据*mut T
指向类型T的可读写裸指针,无生命周期信息,可写数据Rc
智能指针,指向类型T的引用计数指针,共享所有权,线程不安全Arc
智能指针,指向类型T的原子型引用计数指针,共享所有权,线程安全Cow<'a,T>
智能指针,指向类型T的写时复制指针(clone-on-write),可能借用,也可能所有权。类型转换:
通过std::mem::size_of
可测量空间占用。unit和空struct占用空间为0。
tuple, a.0,a.1 也可以访问。什么都没有的tuple叫做unit。
struct, 内存布局与C不同,所以如果要在FFI中使用需要添加#[repr(C)]
类似的结构
tuple struct
enum, 多个类型或的关系。
递归类型:
rust struct Recursive { data: i32, rec: Recursive, } // 上面错误,因为无法确定rec的内存大小 // 解决办法很简单,用指针间接引用就可以了,因为指针的大小是固定的 struct Recursive { data: i32, rec: Box
LEFT OP=RIGHT这种写法,含义等同于LEFT=LEFT OP RIGHT
。所以,y+=x
的意义相当于y=y+x
,依此类推。
Rust不支持++、–运算符,请使用+=1、-=1替代。
语句和表达式的区分方式是后面带不带分号(;)。
如果带了分号,意味着这是一条语句,它的类型是()
;如果不带分号,它的类型就是表达式的类型。
loop可以选择跳出位置 或 返回一个值:
fn main1() {
// A counter variable
let mut m = 1;
let n = 1;
'a: loop {
if m < 100 {
m += 1;
} else {
'b: loop {
if m + n > 50 {
println!("break");
break 'a;
} else {
continue 'a;
}
}
}
}
}
fn main2() {
let v = loop {
break 10;
};
println!("{}", v);
}
Rust支持一种特殊的发散函数(Diverging functions),它的返回类型是感叹号!
当前版本的Rust暂时还不支持尾递归优化,因此如果递归调用层次太多的话,是有可能撑爆栈空间的。尽量使用其他方式进行。
trait 是Rust中一个非常重要的概念。中文翻译为“特征”、“特点”、“特性”。
trait Shape {
fn area(&self) -> f64;
}
其中的self
很关键,所有的trait都有一个隐藏的Self(大写),代表当前这个实现了trait的具体类型,trait定义的函数也被称为“关联函数”。
函数的第一个参数如果是self(小写,一定要在第一个参数位置上,称为receiver 接收者)则说明他是一个方法,可以通过点访问。没有receiver的函数称之为静态函数,只能通过双冒号访问。
trait方法的self参数可以是基于它的一个变体self, &self, mut self, &mut self
。
use std::sync::Arc;
use std::sync::Mutex; // RwLock
use std::thread;
const COUNT: u32 = 1000_0000;
fn main() {
let global = Arc::new(Mutex::new(0));
let clone1 = global.clone();
let th1 = thread::spawn(move || {
for _ in 0..COUNT {
let mut v = clone1.lock().unwrap();
*v += 1;
}
});
let clone2 = global.clone();
let th2 = thread::spawn(move || {
for _ in 0..COUNT {
let mut v = clone2.lock().unwrap();
*v += 1;
}
});
th1.join().ok();
th2.join().ok();
println!("the final value: {:?}", global);
}
跨线程通信
use std::sync::mpsc::channel;
use std::thread;
// sync_channel是阻塞通道,用法同channel.
fn main() {
let (tx, rx) = channel();
for j in 0..5{
let tx_cp = tx.clone();
thread::spawn( move||{
for i in 0..10{
tx_cp.send(i+j*100).unwrap();
}
});
}
drop(tx); // 减一个引用计数
while let Ok(r) = rx.recv() {
println!("{}", r);
}
println!("Over");
}
--crate-type [bin|lib|rlib|dylib|cdylib|staticlib|proc-macro]
其中cdylib和staticlib就是与C的ABI兼容的动态库和静态库,一般使用有两种方式:
rustc --crate-type=staticlib xxx.ts
#![crate-type="staticlib"]
在rust中extern fn
等价于extern "C" fn
,使用#[no_mangle]
修饰函数,避免名字重整。
Demo
RUST生成C库(动态,静态)
// Cargo.toml
// [lib]
// crate-type = ["dylib"] // staticlib
// [dependencies]
// libc=""
// lib.rs
extern crate libc;
use libc::c_char;
#[no_mangle]
pub extern fn rust_capitalize(s: *mut c_char) {
unsafe {
let mut p = s as *mut u8;
while *p != 0 {
let ch = char::from(*p);
if ch.is_ascii() {
let upper = ch.to_ascii_uppercase();
*p = upper as u8;
}
p = p.offset(1);
}
}
}
cargo build --release --lib
RUST调用C库(静态调用)
extern crate libc;
use libc::*;
#[link(name="simple_math")]
extern "C" {
fn add_square(a:c_int, b:c_int) -> c_int;
}
fn main(){
let r = unsafe{ add_square(2,3) };
println!("{}", r);
}