Skip to content

错误处理

Targo 遵循 Go 风格错误处理。普通失败通过返回值传递,而不是抛出异常。

核心规则

  • 可能失败的操作优先使用 [T, error | null]
  • 在调用点显式检查错误。
  • panic()recover() 保留给异常或不可恢复的情况,不用于普通失败。
  • 优先显式包装或返回错误,而不是依赖异常风格的控制流。

常见错误返回模式

typescript
const [data, err] = loadConfig(path);
if (err != null) {
  return [zero<Result>(), err];
}
return [data, null];

有意忽略值

当只关心元组的一侧时,保持被忽略的值显而易见:

typescript
const [_data, err] = loadConfig(path);
if (err != null) {
  return err;
}
return null;
typescript
const [value, _err] = maybeReadCached(path);
return value;

如果项目有更强的本地约定,遵循该约定。否则优先使用 _err_value 这样的显式占位名。

Comma-Ok 风格结果

不是所有元组返回都是错误返回。有些 API 返回值加存在标志:

typescript
const [value, ok] = cache.Get(key);
if (!ok) {
  return [zero<Item>(), new Error("missing item")];
}
return [value, null];

把这些当作 Go 风格多返回值 API,而不是 JavaScript 解构语法糖。

错误构造

typescript
import { New } from "errors";

return [zero<Result>(), New("missing config")];
typescript
import { Errorf } from "fmt";

return [zero<Result>(), Errorf("invalid config %s: %v", name, err)];

实践建议

  • 返回值立即使用时,在调用点附近解构。
  • 如果结果需要在多个分支中传递,引入命名局部变量而不是重复调用函数。
  • 优先使用显式分支流,而不是把所有东西压缩到嵌套条件表达式中。

常见错误

  • [T, error | null] 当成 Promise 结果。
  • 直接翻译 try/catch 而不是重新设计函数契约。
  • 在尝试普通元组解构之前搜索代码库中的"特殊语法"。
  • 把忽略值隐藏得太深,导致控制流不清晰。
  • 在同一路径中混用错误返回元组和异常风格控制流。
  • panic() 用于日常业务错误。

推荐模式

Ok-chain 用于顺序可失败操作

ok() 是一个内置函数,将 [T, error | null] 结果包装为可链式调用的管道,避免嵌套的 if-err 检查:

typescript
// 代替嵌套 if-err:
function loadNumber(path: string): [int, error | null] {
  return ok(readLine(path))
    .flatMap<int>(s => Atoi(s))
    .unwrap();
}

链式方法(非终结):mapflatMapmapErrorElsetaptapErr 终结方法(结束链):unwrapmustorDefaultorZerofold

typescript
// mapErr 包装错误并添加上下文
ok(loadConfig(path))
  .mapErr(err => Errorf("config failed: %v", err))
  .unwrap();

// orDefault 提供回退值
const settings = ok(loadConfig(path))
  .map(config => parseSettings(config))
  .orDefault(defaultSettings);

错误包装与上下文

typescript
import { Errorf } from "fmt";

const [user, err] = findUser(id);
if (err != null) {
  return [zero<Response>(), Errorf("findUser(%d): %v", id, err)];
}