我们都知道 rust 是一种静态类型的语言,意味着它的参数类型必须的固定的,有些时候,我们可能会认为这是一个负担,例如下面的代码:
use aliyun_oss_client::Query;
let query = Query::new();
let response = client.get_object_list(query).await;
println!("objects list: {:?}", response);
来源 aliyun_oss_client - Rust (docs.rs)
因为 Query 里面包含了一个 HashMap,里面需要传递多组参数,例如:
use aliyun_oss_client::Query;
let mut query = Query::new();
query.insert("max-keys", "5");
query.insert("prefix", "babel");
let result = client.get_bucket_info().unwrap().get_object_list(query).unwrap();
来源 aliyun_oss_client::blocking - Rust (docs.rs)
对于第二个例子,我们还是可以接受的,在当前作用域里导入 Query 是必须要的,因为确实需要传递参数,所以说,看到第一个例子的时候,我们想当然的会认为,代码比较丑,rust好丑... 但是这是可以优化的,
我们可以更改函数的签名:
// before
pub async fn get_object_list(self, query: Query) -> OssResult<ObjectList> {
...
}
// now
pub async fn get_object_list<Q: Into<Query>>(self, query: Q) -> OssResult<ObjectList> {
let query = query.into();
...
}
将参数 query 的类型改为可转换为 Query 类型的类型,然后在 Query 类型定义的地方,加一些 Form<T>
语句:
impl<K, V> From<Vec<(K, V)>> for Query
where
K: Into<QueryKey>,
V: Into<QueryValue>,
{
fn from(vec: Vec<(K, V)>) -> Self {
let mut query = Query::with_capacity(vec.len());
for (key, val) in vec {
query.insert(key, val);
}
query
}
}
impl From<[(); 0]> for Query {
/// 空数组转换成 Query
fn from(_: [(); 0]) -> Self {
Self::with_capacity(0)
}
}
来源 oss-rs/types.rs at master · tu6ge/oss-rs (github.com)
这样,我们就可以像这样调用 get_object_list
方法了:
let response = client.get_object_list([]);
println!("objects list: {:?}", response);
let response = client.get_object_list(vec![("max-keys", "5"), ("prefix", "babel")]);
println!("objects list: {:?}", response);
然后我们就可以把丑陋的 use 语句扔掉了:
use aliyun_oss_client::Query;