Goroutines vs Async/Await
Concurrent and asynchronous programming
Introduction
In this lesson, you'll learn about goroutines vs async/await in TypeScript. Coming from Go, you already have a foundation for understanding this concept. We'll build on that knowledge while highlighting the key differences.
In Go, you're familiar with concurrent and asynchronous programming.
TypeScript has its own approach to concurrent and asynchronous programming, which we'll explore step by step.
The TypeScript Way
Let's see how TypeScript handles this concept. Here's a typical example:
// Promise - async operation
async function fetchData(): Promise<string> {
const response = await fetch("/api/data");
return response.text();
}
// Concurrent with Promise.all
const [user, posts] = await Promise.all([
fetchUser(42),
fetchPosts(42),
]);
// Sequential async
async function processAll(ids: number[]): Promise<void> {
for (const id of ids) {
await process(id);
}
}
// Parallel with Promise.allSettled
const results = await Promise.allSettled(
ids.map(id => process(id))
);Comparing to Go
Here's how you might have written similar code in Go:
// Goroutine - lightweight thread
go func() {
result := fetchData()
fmt.Println(result)
}()
// Channel for communication
ch := make(chan string)
go func() {
ch <- "data ready"
}()
msg := <-ch
// WaitGroup for multiple goroutines
var wg sync.WaitGroup
for i := 0; i < 5; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
process(id)
}(i)
}
wg.Wait()You may be used to different syntax or behavior.
Go goroutines are OS-scheduled; TypeScript async/await is event-loop based
You may be used to different syntax or behavior.
Go uses channels for communication; TypeScript uses Promises and callbacks
You may be used to different syntax or behavior.
Go can truly run code in parallel; TypeScript/JS is single-threaded (Node.js workers exist)
You may be used to different syntax or behavior.
Go's WaitGroup → Promise.all for waiting on multiple concurrent tasks
Step-by-Step Breakdown
1. Starting Concurrent Work
Go launches goroutines with the go keyword; TypeScript marks functions async and uses await to pause execution.
go processData()await processData(); // or: processData() // fire-and-forget2. Waiting for Multiple Tasks
Go's WaitGroup or channel patterns correspond to Promise.all in TypeScript for running multiple async tasks concurrently.
results := make([]string, len(ids))
var wg sync.WaitGroup
for i, id := range ids { wg.Add(1); go func(i, id int) { defer wg.Done(); results[i] = fetch(id) }(i, id) }
wg.Wait()const results = await Promise.all(ids.map(id => fetch(id)));3. Error Handling in Async
In Go, goroutine errors must be passed back via channels. In TypeScript, async function errors become rejected Promises caught with try/catch.
Common Mistakes
When coming from Go, developers often make these mistakes:
- Go goroutines are OS-scheduled; TypeScript async/await is event-loop based
- Go uses channels for communication; TypeScript uses Promises and callbacks
- Go can truly run code in parallel; TypeScript/JS is single-threaded (Node.js workers exist)
Key Takeaways
- Go goroutines → TypeScript async functions
- Go channels → TypeScript Promises
- WaitGroup → Promise.all
- Go is truly parallel; TypeScript is single-threaded event loop