linuxfood has created bindings for sqlite3,我很感激。我刚开始学习Rust(0.8),我正在努力理解这段代码到底在做什么:
extern mod sqlite;
fn db() {
let database =
match sqlite::open("test.db") {
Ok(db) => db,
Err(e) => {
println(fmt!("Error opening test.db: %?", e));
return;
}
};
我基本上了解它在做什么。它试图获取数据库连接并测试错误。我不明白它是如何做到的。
为了更好地理解它,我想在没有match
语句的情况下重写它,但我没有这方面的知识。那可能吗? sqlite::open()
会返回两个变量,还是仅返回一个?
如果没有match
语句,该示例如何以不同方式编写?我不是说这是必要的或可取的,但它可以帮助我学习这门语言。
答案 0 :(得分:8)
外部语句是一个赋值,它将匹配表达式的值赋给database
。匹配表达式取决于sqlite::open
的返回值,该值可能是Result<T, E>
类型(带有变体Ok(T)
和Err(E)
的枚举)。如果它是Ok
,则枚举变体有一个参数,匹配表达式将其解构为db
并传回该值(因此它被赋值给变量database
)。如果它是Err
,则enum变体有一个带有错误对象的参数,该参数被打印并且函数返回。
如果不使用匹配语句,可以像下面那样编写(只是因为你明确要求不使用匹配 - 大多数人都会考虑这种错误的编码风格):
let res = sqlite::open("test.db");
if res.is_err() {
println!("Error opening test.db: {:?}", res.unwrap_err());
return;
}
let database = res.unwrap();
答案 1 :(得分:5)
我自己只是在学习Rust,但这是解决这个问题的另一种方法。
import io.dropwizard.lifecycle.Managed;
import java.util.concurrent.Future;
import com.codahale.metrics.health.HealthCheck;
public class ManagedBean extends HealthCheck implements Managed {
private final String name;
private final ManagedThreadPool threadPool;
private final ApplicationProcessor processor;
private Future<?> future; // HERE sonarqube complains..
public ManagedBean( String name, ManagedThreadPool threadPool, ApplicationProcessor processor ) {
this.name = name;
this.threadPool = threadPool;
this.processor = processor;
}
@Override
public void start() throws Exception {
future = threadPool.submit( processor );
}
@Override
public void stop() throws Exception {
if ( !future.isDone() ) {
future.cancel( true );
}
}
@Override
protected Result check() throws Exception {
return processor.getHealthCheck().execute();
}
}
答案 2 :(得分:4)
This function open
returns SqliteResult<Database>
;根据定义pub type SqliteResult<T> = Result<T, ResultCode>
,即std::result::Result<Database, ResultCode>
。
Result
是一个enum,你根本无法在不匹配的情况下访问枚举的变体:也就是说,这是唯一的方法。当然,你可能有方法来抽象匹配,但它们必须用匹配来实现。
你可以从结果文档中看到它确实有像is_err
这样的方便方法,大概是这个(它不是这个,但足够接近):
fn is_err(&self) -> bool {
match *self {
Ok(_) => false,
Err(_) => true,
}
}
和unwrap
(再次只是近似):
fn unwrap(self) -> T {
match self {
Ok(t) => t,
Err(e) => fail!(),
}
}
如您所见,这些是通过匹配实现的。在你的这种情况下,使用匹配是编写此代码的最佳方式。
答案 3 :(得分:3)
sqlite::open()
正在返回枚举。枚举在生锈方面略有不同,枚举的每个值都可以附加字段。
见http://static.rust-lang.org/doc/0.8/tutorial.html#enums
因此,在这种情况下,SqliteResult
枚举可以是Ok
或Err
,如果它是Ok
那么它就会引用附加到它的数据库,如果它是Err
然后它有错误详细信息。
使用C#或Java背景,您可以将SqliteResult
视为Ok
和Err
继承的基类,每个基类都有自己的相关信息。在这种情况下,match子句只是检查类型以查看返回的子类型。我不会过于注重这个并行,尽管尝试这种语言之间的概念是一个坏主意。