Rust异步函数返回Result报错:无法转换azure_core错误为String
Rust + Actix + Azure CosmosDB 编译错误:
?运算符无法转换错误类型 问题描述
我是Rust新手,正在结合Rust、Actix与Azure CosmosDB开发。编写了一个异步函数,期望连接CosmosDB并返回包含集合名称的Result<String, String>,但遇到编译错误:?运算符无法将azure_core::error::Error转换为std::string::String。
代码
async fn datastuff() -> Result<String, String> { let primary_key = std::env::var("COSMOSDB_READKEY").expect("Set env variable COSMOS_PRIMARY_KEY first!"); let account = std::env::var("COSMOSDB_ACCOUNT").expect("Set env variable COSMOS_ACCOUNT first!"); let database_name = "azdeployer"; let collection_name = "resourcetemplates"; // First, create an authorization token. There are two types of tokens: primary and resource constrained. // Please check the Azure documentation or the examples folder on how to create and use token-based permissions. let authorization_token = AuthorizationToken::primary_key(&primary_key)?; // Next we will create a Cosmos client. let client = CosmosClient::new(account, authorization_token); // We know the database so we can obtain a database client. let database = client.database_client(database_name); // We know the collection so we can obtain a collection client. let collection = database.collection_client(collection_name); //let cosmos_collection_client: CollectionClient = cosmos::cosmosclient::create_collection_client().expect("prutser"); //let document_client: DocumentClient = cosmos_collection_client.document_client("resourceGroups@2022-09-01", "resourcegroup"); let documents1 = collection.list_documents(); let documents = collection.collection_name(); let result: String = documents.to_string(); Ok(result) }
错误信息
错误[E0277]:`?`无法将错误转换为`std::string::String` --> src\main.rs:17:76 | 17 | let authorization_token = AuthorizationToken::primary_key(&primary_key)?; | ^ 未为`std::string::String`实现`trait std::convert::From<azure_core::error::Error>` | = 说明:问号运算符(`?`)会通过`From`trait隐式转换错误值 = 帮助:以下类型实现了`trait std::convert::From<T>`: <std::string::String as std::convert::From<char>> <std::string::String as std::convert::From<bytestring::ByteString>> <std::string::String as std::convert::From<Box<str>>> <std::string::String as std::convert::From<uuid::Uuid>> <std::string::String as std::convert::From<Cow<'a, str>>> <std::string::String as std::convert::From<url::Url>> <std::string::String as std::convert::From<&str>> <std::string::String as std::convert::From<&mut str>> <std::string::String as std::convert::From<&std::string::String>> = 说明:需要`Result<std::string::String, std::string::String>`实现`FromResidual<Result<Infallible, azure_core::error::Error>>` 部分错误有详细解释:E0277, E0425。如需了解错误详情,尝试`rustc --explain E0277`。
解决方案
问题根源
AuthorizationToken::primary_key方法返回的错误类型是azure_core::error::Error,但你的函数声明返回Result<String, String>。?运算符要求错误类型之间必须实现std::convert::Fromtrait以自动转换,而String并没有为azure_core::error::Error实现这个trait,因此编译失败。
解决方法
方法1:直接将错误转为字符串(快速修复)
使用map_err方法把azure_core::error::Error转换为String,替换原代码中的?用法:
let authorization_token = AuthorizationToken::primary_key(&primary_key) .map_err(|e| e.to_string())?;
这样错误会被转为字符串形式,符合函数返回的错误类型要求。
方法2:自定义错误类型(推荐,适合大型项目)
定义一个包含所有可能错误的枚举,为其实现From<azure_core::error::Error>、std::fmt::Display和std::error::Errortrait,让?可以自动转换错误类型:
use std::error::Error; use std::fmt; #[derive(Debug)] enum MyError { CosmosError(azure_core::error::Error), EnvVarError(std::env::VarError), } impl From<azure_core::error::Error> for MyError { fn from(e: azure_core::error::Error) -> Self { MyError::CosmosError(e) } } impl From<std::env::VarError> for MyError { fn from(e: std::env::VarError) -> Self { MyError::EnvVarError(e) } } impl fmt::Display for MyError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { MyError::CosmosError(e) => write!(f, "CosmosDB error: {}", e), MyError::EnvVarError(e) => write!(f, "Environment variable error: {}", e), } } } impl Error for MyError {} // 修改函数返回类型 async fn datastuff() -> Result<String, MyError> { let primary_key = std::env::var("COSMOSDB_READKEY")?; let account = std::env::var("COSMOSDB_ACCOUNT")?; // 后续代码不变,?会自动转换错误到MyError let authorization_token = AuthorizationToken::primary_key(&primary_key)?; let client = CosmosClient::new(account, authorization_token); let database = client.database_client("azdeployer"); let collection = database.collection_client("resourcetemplates"); let result = collection.collection_name().to_string(); Ok(result) }
内容的提问来源于stack exchange,提问作者Cyriel Lamerigts
相关产品推荐
相关产品推荐

