[易学易懂系列|rustlang语言|零基础|快速入门|(28)|实战5:实现BTC价格转换工具]
项目实战
实战5:实现BTC价格转换工具
今天我们来开发一个简单的BTC实时价格转换工具。
我们首先创建一个目录:
1
2 1cargo new btc_converter
2
我们用TDD方式来开发。
然后 我们先写一些测试代码。
在src/main.rs下面,增加代码如下:
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 1#[cfg(test)]
2mod tests {
3 use super::*;
4
5 #[test]
6 fn test_convert_success() {
7 match convert_btc(1.2, "BTC", "USD") {
8 Ok(_) => assert!(true),
9 Err(_) => assert!(false),
10 }
11 }
12 #[test]
13 fn test_convert_success2() {
14 match convert_btc(2.1, "BTC", "MKD") {
15 Ok(_) => assert!(true),
16 Err(_) => assert!(false),
17 }
18 }
19
20 #[test]
21 fn test_convert_error_wrong_from() {
22 match convert_btc(1.2, "wrongvalue", "USD") {
23 Ok(_) => assert!(false),
24 Err(_) => assert!(true),
25 }
26 }
27
28 #[test]
29 fn test_convert_error_wrong_to() {
30 match convert_btc(1.2, "USD", "wrongvalue") {
31 Ok(_) => assert!(false),
32 Err(_) => assert!(true),
33 }
34 }
35}
36
37
我们运行命令:
1
2 1cargo test
2
结果肯定是不通过。
我现在我们来增加核心业务代码 :
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 1const API_URL: &str = "https://apiv2.bitcoinaverage.com/convert/global";
2
3//错误信息
4#[derive(From, Display, Debug)]
5enum BtcError {
6 ApiError,
7 Reqwest(reqwest::Error),
8}
9//响应信息结构体
10#[derive(Deserialize, Debug)]
11struct BtcResponse {
12 time: String,
13 success: bool,
14 price: f64,
15}
16
17
18//价格转换,直接调用相关API
19fn convert_btc(amount: f64, from: &str, to: &str) -> Result<BtcResponse, BtcError> {
20 use BtcError::*;
21 println!("---convert_btc-----{:?},{:?}", from, to);
22 let client = reqwest::Client::new();
23 let request =
24 client
25 .get(API_URL)
26 .query(&[("from", from), ("to", to), ("amount", &amount.to_string())]);
27 let response_result: BtcResponse = request.send()?.json()?;
28
29 if !response_result.success {
30 return Err(ApiError);
31 }
32
33 return Ok(response_result);
34}
35
然后,我们再跑一下测试用例。
现在应该都通过 了。
当然我们要引用相关包:
1
2
3
4
5
6
7
8
9 1[dependencies]
2reqwest = "0.9.12"
3serde_derive = "1.0.89"
4serde = "1.0.89"
5serde_json = "1.0.39"
6structopt = "0.2.15"
7derive_more = "0.14.0"
8
9
src/main.rs完整代码如下:
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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118 1#[macro_use]
2extern crate serde_derive;
3#[macro_use]
4extern crate derive_more;
5use reqwest;
6use std::process::exit;
7use structopt::StructOpt;
8
9fn main() {
10 let opt = Opt::from_args();
11
12 let response = match convert_btc(opt.amount, &opt.from, &opt.to) {
13 Ok(value) => value,
14 Err(e) => {
15 println!("A error occurred when try to get value from api");
16 if opt.verbose {
17 println!("Message: {} - Details: {:?}", e, e);
18 }
19 exit(1);
20 }
21 };
22
23 if opt.silent {
24 println!("{}", response.price);
25 } else {
26 println!("{} {}", response.price, &opt.to);
27 }
28}
29const API_URL: &str = "https://apiv2.bitcoinaverage.com/convert/global";
30//错误信息
31#[derive(From, Display, Debug)]
32enum BtcError {
33 ApiError,
34 Reqwest(reqwest::Error),
35}
36//响应信息结构体
37#[derive(Deserialize, Debug)]
38struct BtcResponse {
39 time: String,
40 success: bool,
41 price: f64,
42}
43
44#[derive(Debug, StructOpt)]
45#[structopt(
46 name = "btc_converter",
47 about = "Get value of a btc value to a currency"
48)]
49struct Opt {
50 /// Set amount to convert to a currency or from a currency
51 #[structopt(default_value = "1")]
52 amount: f64,
53 /// Set the initial currency of
54 #[structopt(short = "f", long = "from", default_value = "BTC")]
55 from: String,
56 /// Set the final currency to convert
57 #[structopt(short = "t", long = "to", default_value = "USD")]
58 to: String,
59 /// Silent information about currency result
60 #[structopt(short = "s", long = "silent")]
61 silent: bool,
62 /// Verbose errors
63 #[structopt(short = "v", long = "verbose")]
64 verbose: bool,
65}
66fn convert_btc(amount: f64, from: &str, to: &str) -> Result<BtcResponse, BtcError> {
67 use BtcError::*;
68 println!("---convert_btc-----{:?},{:?}", from, to);
69 let client = reqwest::Client::new();
70 let request =
71 client
72 .get(API_URL)
73 .query(&[("from", from), ("to", to), ("amount", &amount.to_string())]);
74 let response_result: BtcResponse = request.send()?.json()?;
75
76 if !response_result.success {
77 return Err(ApiError);
78 }
79
80 return Ok(response_result);
81}
82#[cfg(test)]
83mod tests {
84 use super::*;
85
86 #[test]
87 fn test_convert_success() {
88 match convert_btc(1.2, "BTC", "USD") {
89 Ok(_) => assert!(true),
90 Err(_) => assert!(false),
91 }
92 }
93 #[test]
94 fn test_convert_success2() {
95 match convert_btc(2.1, "BTC", "MKD") {
96 Ok(_) => assert!(true),
97 Err(_) => assert!(false),
98 }
99 }
100
101 #[test]
102 fn test_convert_error_wrong_from() {
103 match convert_btc(1.2, "wrongvalue", "USD") {
104 Ok(_) => assert!(false),
105 Err(_) => assert!(true),
106 }
107 }
108
109 #[test]
110 fn test_convert_error_wrong_to() {
111 match convert_btc(1.2, "USD", "wrongvalue") {
112 Ok(_) => assert!(false),
113 Err(_) => assert!(true),
114 }
115 }
116}
117
118
API地址:
https://apiv2.bitcoinaverage.com
以上,希望对你有用。
1
2 1如果遇到什么问题,欢迎加入:rust新手群,在这里我可以提供一些简单的帮助,加微信:360369487,注明:博客园+rust
2