rust 实用代码总结

获取当前的时间戳

示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
use std::time::{SystemTime};
fn get_timestamp() -> u64 {
match SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) {
Ok(now) => {
now.as_secs()
},
_ => {
std::u64::MAX
},
}
}

fn main() {
println!("Hello, world! now={}", get_timestamp());
}

实现函数重载

函数重载
rust本身不支持函数重载,但是可以用泛型trait实现类似于重载的效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
pub trait With<T> {
fn with(value: T) -> Self;
}

struct Foo {
bar: String,
baz: i32,
quux: bool,
}

impl Default for Foo {
fn default() -> Self {
Foo {
bar: "".to_string(),
baz: 0,
quux: false,
}
}
}

impl Foo {
fn new() -> Self {
Foo {
..Default::default()
}
}
}

impl With<String> for Foo {
fn with(x: String) -> Self {
Foo {
bar: x,
..Default::default()
}
}
}

impl With<i32> for Foo {
fn with(x: i32) -> Self {
Foo {
baz: x,
..Default::default()
}
}
}

impl With<bool> for Foo {
fn with(x: bool) -> Self {
Foo {
quux: x,
..Default::default()
}
}
}

#[test]
fn name() {
let a = Foo::with(1);
}

vec合并数据时防止出现拷贝的方法

当结构体中使用Vec在头部插入一个新的Vec数据时可以通过mem::replace方法来减少数据的拷贝。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
use std::mem;
struct Myvec {
data: Vec<u8>,
count: usize,
}

impl Myvec {
fn new() -> Myvec {
Myvec {
data : Vec::new(),
count : 0,
}
}

fn append(&mut self, d:&mut Vec<u8>) {
self.data.append(d);
}

fn pre_insert(&mut self, d:Vec<u8>) {
// 使用replace 逆向实现数据的插入,防止clone数据
let mut old = mem::replace(&mut self.data, d);
self.data.append(&mut old);
}

fn push(&mut self, u:u8) {
self.data.push(u);
}

fn print(&self) {
println!("data{:#?}", self.data);
}
}

fn main() {
let mut v1 = Myvec::new();
let mut v2:Vec<u8> = Vec::new();
v2.push(3);
v2.push(4);
v1.push(1);
v1.push(2);
v1.pre_insert(v2);
v1.print();
}

打印变量地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
fn main(){
let a:i32 = 5;
//&a先转成raw指针,然后再把指针转成usize,这个可以print的
let addr = &a as *const i32 as usize;
println!("addr:0x{:X}",addr);

//为了验证刚才的地址是不是正确的,我们修改这个指针指向的数据
//pa就是addr对应的raw指针
let pa = addr as *mut i32;
//解引用,*pa其实就是&mut a了,给他赋值100
unsafe{*pa = 100};

//打印a,可以看到a已经变成100了
println!("value:{}",a);
}

打印变量T的类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
fn print_type_of<T>(_: &T) {
println!("{}", std::any::type_name::<T>())
}
fn main() {
let s = String::from("hello");
let bytes = s.into_bytes();
assert_eq!(&[104, 101, 108, 108, 111][..], &bytes[..]);
print_type_of(&bytes);
let mut mb = bytes;
print_type_of(&mb);
print_type_of(&mut mb);
let mut x = &mut mb;
print_type_of(&x);
let y = &mut x;
print_type_of(&y);
}

同一个crate内 不同lib或程序间的引用

在同一个大型项目中,可能会建立多个lib,有时候想要以外部调用库的方式测试其中的某个lib的某项功能,这时怎么修改Cargo.toml文件引用工程内的某个lib?
答案是修改Cargo.toml 文件中的[dependencies]

参考arnl/test_simple/test_redis/Cargo.toml

1
2
3
4
5
6
7
8
9
10
11
[package]
name = "test_redis"
version = "0.1.0"
authors = ["wanghaibin <wanghaibin@qiyi.com>"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
redis = { path = "../../src/libredis/" }

在非tests目录下的测试程序arnl/test_simple/test_redis/src内容如下

1
2
3
4
5
6
7
8
9
use redis::{redis_string, redis_client};

fn main() {
println!("Hello, world!");
let mut stream = redis_client::RedisClient::new("127.0.0.1:6379", &0, &3).unwrap();
let mut rstr = redis_string::RedisString::new(&mut stream);
let key = "incrbyfloat_test";
println!("xxxx={:#?}",rstr.incrbyfloat(key, 2.1));
}

有趣的所有权问题问题

代码1

1
2
3
4
5
6
fn main() {
let mut v = vec![1,2,3];
let first = &v[0];
v.push(5);
println!("Hello, world!, first={}", first);
}

代码2

1
2
3
4
5
6
7
fn main() {
let mut v = vec![1,2,3];
let first = &v[0];
println!("Hello, world!, first={}", first);
v.push(5);
}

上述代码1会编译报错,提示error[E0502]: cannot borrow v as mutable because it is also borrowed as immutable

代码2却可以正常编译通过,为什么那?

个人认为这正是rust在在编译期发现问题的优点之一,代码1报借用和可变借用同时存在错误,是因为在print的时候使用first,这时进行所有权规则检查,发现了E0502错误。而代码2为什么没有报错,是因为在编译时,运行到print进行所有权检测,此时还没有发生所有权问题,而在检测后续的push时first已经没有任何引用或使用,所以相关所有权规则没有问题


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!