Skip to content

并发

Targo 的并发模型来自 Go,而不是 JavaScript 的 async runtime。

核心规则

  • 不支持 async/awaitPromise
  • 使用 go(() => { ... }) 启动 goroutine
  • 使用 chan<T> 进行通信
  • 使用 switch (chan.$select) 进行 select 风格协调
  • 使用 defer 在函数返回时执行清理
  • 显式设计数据流和错误流,不要假设存在 JavaScript 异步运行时模型

Goroutine

使用 go() 启动 goroutine:

typescript
const ch = new chan<string>(1);

go(() => {
  const result = compute();
  ch.$send(result);
});

const value = ch.$recv();

Goroutine 不是 Promise 包装器。只有在并发确实带来价值时才使用。

Channel

Channel 是 goroutine 之间的主要通信机制。

typescript
// 无缓冲 channel
const ch = new chan<int>();

// 有缓冲 channel
const buffered = new chan<string>(10);

// 发送
ch.$send(42);

// 接收
const value = ch.$recv();

// 关闭
ch.$close();

Select

使用 switch (chan.$select) 等待多个 channel 操作:

typescript
const dataCh = new chan<string>(1);
const doneCh = new chan<void>(1);

switch (chan.$select) {
  case dataCh.$recv(): {
    const msg = dataCh.$recv();
    console.log(msg);
    break;
  }
  case doneCh.$recv(): {
    console.log("done");
    break;
  }
}

Defer

defer 安排一个函数调用在外层函数返回时执行:

typescript
function processFile(path: string): error | null {
  const [f, err] = os.Open(path);
  if (err != null) {
    return err;
  }
  defer(() => f.Close());

  // ... 使用 f ...
  return null;
}

实践模式

需求优先选择
后台并发工作goroutine + channel
等待多个通信路径switch (chan.$select)
超时风格协调Go 风格 time + channel 流
函数退出时清理defer

常见错误

  • 把 goroutine 当成 Promise 包装器
  • 只设计成功 channel,忘记失败路径
  • 发送方完成后不关闭 channel
  • 试图一对一翻译 Promise.allraceawait
  • 忘记 defer 在函数返回时执行,而不是在块退出时