Concurrency
Targo's concurrency model comes from Go, not from JavaScript's async runtime.
Core Rules
async/awaitandPromiseare not supported.- Use
go(() => { ... })for goroutines. - Use
chan<T>for communication. - Use
switch (chan.$select)for select-style coordination. - Use
deferfor cleanup that should run when the enclosing function returns. - Design the data flow and error flow explicitly. Do not assume a JavaScript async runtime model exists underneath.
Goroutines
Start a goroutine with go():
typescript
const ch = new chan<string>(1);
go(() => {
const result = compute();
ch.$send(result);
});
const value = ch.$recv();Goroutines are not Promise wrappers. Only use them when concurrent execution actually provides value.
Channels
Channels are the primary communication mechanism between goroutines.
typescript
// Unbuffered channel
const ch = new chan<int>();
// Buffered channel
const buffered = new chan<string>(10);
// Send
ch.$send(42);
// Receive
const value = ch.$recv();
// Close
ch.$close();Channel Direction
Use typed channel directions when a function only needs to send or receive:
typescript
function producer(out: chan<int>): void {
out.$send(1);
out.$send(2);
out.$close();
}Select
Use switch (chan.$select) for waiting on multiple channel operations:
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 schedules a function call to run when the enclosing function returns:
typescript
function processFile(path: string): error | null {
const [f, err] = os.Open(path);
if (err != null) {
return err;
}
defer(() => f.Close());
// ... work with f ...
return null;
}Practical Patterns
| Need | Prefer |
|---|---|
| Background concurrent work | goroutine + channel |
| Waiting on multiple communication paths | switch (chan.$select) |
| Timeout-style coordination | Go-style time + channel flow |
| Cleanup on function exit | defer |
Common Mistakes
- Using goroutines as if they were just a Promise wrapper.
- Designing only a success channel and forgetting the failure path.
- Not closing channels when the sender is done.
- Trying to translate
Promise.all,race, orawaitone-to-one. - Forgetting that
deferruns at function return, not at block exit.