错误处理
Fleet 语言提供了强大而安全的错误处理机制,通过 Option 和 Result 类型来处理可能失败的操作,避免运行时崩溃。
📋 目录
🎯 错误处理哲学
Fleet 的错误处理原则
Fleet 采用显式错误处理,让错误成为类型系统的一部分:
// ❌ 传统方式 - 可能崩溃
fn divide_unsafe(a: int, b: int) -> int {
return a / b; // 如果 b 为 0 会崩溃
}
// ✅ Fleet 方式 - 安全处理
fn divide_safe(a: int, b: int) -> Option {
if b == 0 {
return Option::None;
} else {
return Option::Some(a / b);
}
}
错误处理的优势
- 编译时检查 - 强制处理所有可能的错误
- 类型安全 - 错误信息包含在类型中
- 可组合性 - 错误处理可以链式组合
- 性能 - 零成本抽象,无运行时开销
🔍 Option 类型
Option 基础
Option 类型表示一个值可能存在也可能不存在:
enum Option {
Some(int), // 目前只支持具体类型,暂不支持泛型
None,
}
fn find_user(id: int) -> Option {
if id == 1 {
return Option::Some(1); // 返回用户ID,因为Option目前只支持int
} else if id == 2 {
return Option::Some(2);
} else {
return Option::None;
}
}
fn main() {
let user = find_user(1);
match user {
Option::Some(name) => print("Found user: " + name),
Option::None => print("User not found"),
}
}
Option 方法
fn main() {
let maybe_number = Option::Some(42);
let empty_option = Option::None;
// is_some() 和 is_none()
print("Has value: " + maybe_number.is_some()); // true
print("Is empty: " + empty_option.is_none()); // true
// unwrap() - 获取值(如果为 None 会 panic)
let value = maybe_number.unwrap();
print("Value: " + value); // 42
// unwrap_or() - 提供默认值
let default_value = empty_option.unwrap_or(0);
print("Default value: " + default_value); // 0
// unwrap_or_else() - 使用函数计算默认值
let computed_default = empty_option.unwrap_or_else(|| {
print("Computing default...");
return 100;
});
print("Computed default: " + computed_default); // 100
}
Option 链式操作
fn parse_number(s: str) -> Option {
// 模拟解析数字
if s == "42" {
return Option::Some(42);
} else {
return Option::None;
}
}
fn double(x: int) -> int {
return x * 2;
}
fn main() {
let input = "42";
// map - 转换 Option 内部的值
let doubled = parse_number(input).map(double);
match doubled {
Option::Some(value) => print("Doubled: " + value), // 84
Option::None => print("Failed to parse"),
}
// and_then - 链式操作
let result = parse_number(input)
.and_then(|x| {
if x > 0 {
return Option::Some(x * x);
} else {
return Option::None;
}
});
print("Result: " + result.unwrap_or(0)); // 1764
}
Option 过滤
fn main() {
let numbers = [
Option::Some(1),
Option::None,
Option::Some(5),
Option::None,
Option::Some(10),
];
// filter - 根据条件过滤
let large_numbers = numbers
.iter()
.filter_map(|opt| opt.filter(|&x| x > 3))
.collect();
print("Large numbers: " + large_numbers); // [5, 10]
}
⚠️ Result 类型
Result 基础
Result 类型表示操作可能成功或失败:
// 注意:Fleet 目前还未完全实现 Result 类型
// 以下是概念性示例,实际语法可能不同
enum Result {
Ok(int), // 成功值
Err(str), // 错误信息
}
fn divide(a: int, b: int) -> Result {
if b == 0 {
return Result::Err("Division by zero");
} else {
return Result::Ok(a / b);
}
}
fn main() {
let result1 = divide(10, 2);
match result1 {
Result::Ok(value) => print("Result: " + value),
Result::Err(error) => print("Error: " + error),
}
let result2 = divide(10, 0);
match result2 {
Result::Ok(value) => print("Result: " + value),
Result::Err(error) => print("Error: " + error),
}
}
Result 方法
fn main() {
let success = Result::Ok[int, str](42);
let failure = Result::Err[int, str]("Something went wrong");
// is_ok() 和 is_err()
print("Is success: " + success.is_ok()); // true
print("Is failure: " + failure.is_err()); // true
// unwrap() 和 unwrap_err()
let value = success.unwrap();
print("Success value: " + value); // 42
let error = failure.unwrap_err();
print("Error message: " + error); // "Something went wrong"
// unwrap_or() 和 unwrap_or_else()
let safe_value = failure.unwrap_or(0);
print("Safe value: " + safe_value); // 0
}
Result 链式操作
fn parse_int(s: str) -> Result {
if s == "42" {
return Result::Ok(42);
} else {
return Result::Err("Invalid number");
}
}
fn validate_positive(x: int) -> Result {
if x > 0 {
return Result::Ok(x);
} else {
return Result::Err("Number must be positive");
}
}
fn main() {
let input = "42";
// map - 转换成功值
let doubled = parse_int(input).map(|x| x * 2);
print("Doubled: " + doubled.unwrap_or(0)); // 84
// map_err - 转换错误值
let with_context = parse_int("invalid")
.map_err(|e| "Parse error: " + e);
match with_context {
Result::Ok(_) => print("Success"),
Result::Err(e) => print(e), // "Parse error: Invalid number"
}
// and_then - 链式操作
let validated = parse_int(input)
.and_then(validate_positive);
match validated {
Result::Ok(value) => print("Valid positive number: " + value),
Result::Err(error) => print("Validation error: " + error),
}
}
🔄 错误传播
? 操作符
? 操作符提供了简洁的错误传播方式:
fn parse_and_validate(s: str) -> Result {
let number = parse_int(s)?; // 如果失败,直接返回错误
let positive = validate_positive(number)?; // 链式传播
return Result::Ok(positive);
}
// 等价于:
fn parse_and_validate_verbose(s: str) -> Result {
match parse_int(s) {
Result::Ok(number) => {
match validate_positive(number) {
Result::Ok(positive) => return Result::Ok(positive),
Result::Err(error) => return Result::Err(error),
}
},
Result::Err(error) => return Result::Err(error),
}
}
fn main() {
match parse_and_validate("42") {
Result::Ok(value) => print("Success: " + value),
Result::Err(error) => print("Error: " + error),
}
}
错误转换
// 自动错误转换
fn complex_operation(s: str) -> Result {
let number = parse_int(s)?;
let validated = validate_positive(number)?;
let doubled = multiply_by_two(validated)?;
return Result::Ok(doubled);
}
// 手动错误转换
fn with_error_conversion(s: str) -> Result {
let number = parse_int(s)
.map_err(|e| CustomError::ParseError(e))?;
let validated = validate_positive(number)
.map_err(|e| CustomError::ValidationError(e))?;
return Result::Ok(validated);
}
🎨 自定义错误类型
定义错误枚举
enum MathError {
DivisionByZero,
Overflow,
InvalidInput(str),
}
impl Display for MathError {
fn to_string(self) -> str {
match self {
MathError::DivisionByZero => return "Cannot divide by zero",
MathError::Overflow => return "Arithmetic overflow",
MathError::InvalidInput(msg) => return "Invalid input: " + msg,
}
}
}
fn safe_divide(a: int, b: int) -> Result {
if b == 0 {
return Result::Err(MathError::DivisionByZero);
}
let result = a / b;
if result > 1000000 {
return Result::Err(MathError::Overflow);
}
return Result::Ok(result);
}
fn main() {
match safe_divide(10, 0) {
Result::Ok(value) => print("Result: " + value),
Result::Err(error) => print("Error: " + error.to_string()),
}
}
错误链
enum DatabaseError {
ConnectionFailed(str),
QueryFailed(str),
DataNotFound,
}
enum ServiceError {
DatabaseError(DatabaseError),
ValidationError(str),
AuthenticationError,
}
fn fetch_user(id: int) -> Result {
// 验证输入
if id <= 0 {
return Result::Err(ServiceError::ValidationError("Invalid user ID"));
}
// 查询数据库
let user = query_database(id)
.map_err(|db_err| ServiceError::DatabaseError(db_err))?;
return Result::Ok(user);
}
fn main() {
match fetch_user(-1) {
Result::Ok(user) => print("Found user: " + user.name),
Result::Err(ServiceError::ValidationError(msg)) => {
print("Validation error: " + msg);
},
Result::Err(ServiceError::DatabaseError(db_err)) => {
print("Database error: " + db_err.to_string());
},
Result::Err(ServiceError::AuthenticationError) => {
print("Authentication failed");
},
}
}
🔄 错误恢复
重试机制
fn retry_operation(
operation: fn() -> Result,
max_attempts: int
) -> Result {
var attempts = 0;
loop {
attempts = attempts + 1;
match operation() {
Result::Ok(value) => return Result::Ok(value),
Result::Err(error) => {
if attempts >= max_attempts {
return Result::Err(error);
}
print("Attempt " + attempts + " failed, retrying...");
},
}
}
}
fn unreliable_network_call() -> Result {
// 模拟不稳定的网络调用
if random() < 0.7 {
return Result::Err("Network timeout");
} else {
return Result::Ok("Success");
}
}
fn main() {
match retry_operation(unreliable_network_call, 3) {
Result::Ok(data) => print("Got data: " + data),
Result::Err(error) => print("Failed after retries: " + error),
}
}
回退策略
fn get_data_with_fallback(source: DataSource) -> Result {
// 尝试主要数据源
match get_from_primary(source) {
Result::Ok(data) => return Result::Ok(data),
Result::Err(_) => {
print("Primary source failed, trying cache...");
// 尝试缓存
match get_from_cache(source) {
Result::Ok(data) => return Result::Ok(data),
Result::Err(_) => {
print("Cache failed, using default...");
// 使用默认值
return Result::Ok(get_default_data());
},
}
},
}
}
📊 错误收集
收集多个错误
fn validate_user_data(data: UserData) -> Result> {
var errors = [];
// 验证姓名
if data.name.is_empty() {
errors.push("Name cannot be empty");
}
// 验证邮箱
if !is_valid_email(data.email) {
errors.push("Invalid email format");
}
// 验证年龄
if data.age < 0 || data.age > 150 {
errors.push("Age must be between 0 and 150");
}
if errors.is_empty() {
return Result::Ok(ValidatedUser::from(data));
} else {
return Result::Err(errors);
}
}
fn main() {
let user_data = UserData {
name: "",
email: "invalid-email",
age: -5,
};
match validate_user_data(user_data) {
Result::Ok(user) => print("User validated successfully"),
Result::Err(errors) => {
print("Validation failed:");
loop error in errors {
print(" - " + error);
}
},
}
}
🎯 最佳实践
错误处理指南
- 使用类型系统 - 让错误成为类型的一部分
- 提供上下文 - 错误信息应该有助于调试
- 及早失败 - 在错误发生时立即处理
- 文档化错误 - 说明函数可能返回的错误
性能考虑
// ✅ 好的做法 - 使用 Result 进行错误处理
fn parse_config(path: str) -> Result {
let content = read_file(path)?;
let parsed = parse_json(content)?;
return Ok(Config::from(parsed));
}
// ❌ 避免的做法 - 使用异常(Fleet 不支持)
// fn parse_config_bad(path: str) -> Config {
// let content = read_file(path); // 可能抛出异常
// let parsed = parse_json(content); // 可能抛出异常
// return Config::from(parsed);
// }
错误设计原则
- 具体而有用 - 提供足够的信息来诊断问题
- 可操作 - 用户应该知道如何修复错误
- 一致性 - 在整个应用中使用一致的错误处理模式
- 可组合 - 错误应该能够组合和转换
常见模式
// 模式 1: 转换和验证
fn process_input(input: str) -> Result {
let cleaned = clean_input(input)?;
let validated = validate_input(cleaned)?;
let processed = transform_input(validated)?;
return Result::Ok(processed);
}
// 模式 2: 资源管理
fn with_file(path: str, operation: fn(File) -> Result) -> Result {
let file = open_file(path)?;
let result = operation(file);
close_file(file);
return result;
}
// 模式 3: 条件错误
fn conditional_operation(condition: bool) -> Result {
if condition {
return Result::Ok("Success");
} else {
return Result::Err("Condition not met");
}
}