JS
GO

JavaScript to Go

10 lessons

Progress0%
1Variables & Types2Functions3Objects → Structs4Async → Goroutines5Errors & Panic6Interfaces7Slices and Maps8Packages and Modules9Testing10Standard Library
All Mirror Courses
JS
GO
Async → Goroutines
MirrorLesson 4 of 10
Lesson 4

Async → Goroutines

Concurrency patterns

Introduction

In this lesson, you'll learn about async → goroutines in Go. Coming from JavaScript, you already have a foundation for understanding this concept. We'll build on that knowledge while highlighting the key differences.

Mirror Card
JS
From JavaScript:

In JavaScript, you're familiar with concurrency patterns.

GO
In Go:

Go has its own approach to concurrency patterns, which we'll explore step by step.

The Go Way

Let's see how Go handles this concept. Here's a typical example:

GO
Go Example
package main

import "sync"

// Goroutine — lightweight thread
go processItem(id)

// Channel for results
results := make(chan string, len(ids))

var wg sync.WaitGroup
for _, id := range ids {
    wg.Add(1)
    go func(id int) {
        defer wg.Done()
        results <- fetchData(id)
    }(id)
}

// Wait and collect
go func() {
    wg.Wait()
    close(results)
}()

for r := range results {
    fmt.Println(r)
}

Comparing to JavaScript

Here's how you might have written similar code in JavaScript:

JS
JavaScript (What you know)
// Promise-based async
async function fetchData(url) {
  const res = await fetch(url);
  return res.json();
}

// Parallel
const [users, posts] = await Promise.all([
  fetchData("/api/users"),
  fetchData("/api/posts"),
]);

// Sequential
for (const id of ids) {
  await processItem(id);
}
Mirror Card
JS
From JavaScript:

You may be used to different syntax or behavior.

GO
In Go:

Go goroutines are OS-scheduled; JS async is event-loop based

Mirror Card
JS
From JavaScript:

You may be used to different syntax or behavior.

GO
In Go:

Go channels for communication; JS uses Promises and callbacks

Mirror Card
JS
From JavaScript:

You may be used to different syntax or behavior.

GO
In Go:

Go can truly run code in parallel on multiple CPUs; JS is single-threaded

Mirror Card
JS
From JavaScript:

You may be used to different syntax or behavior.

GO
In Go:

sync.WaitGroup replaces Promise.all for multiple goroutines

Step-by-Step Breakdown

1. go Keyword

The 'go' keyword starts a goroutine — a lightweight concurrent function. Unlike async/await, it doesn't block the caller.

JS
JavaScript
await processItem(id);
GO
Go
go processItem(id) // concurrent, non-blocking

2. Channels

Channels pass data safely between goroutines — the Go equivalent of resolving a Promise.

GO
Go
ch := make(chan int)
go func() { ch <- compute() }()
result := <-ch // blocks until value arrives

3. WaitGroup vs Promise.all

sync.WaitGroup tracks when all goroutines complete, equivalent to awaiting Promise.all.

JS
JavaScript
await Promise.all(ids.map(id => process(id)))
GO
Go
var wg sync.WaitGroup
for _, id := range ids { wg.Add(1); go func(id int){ defer wg.Done(); process(id) }(id) }
wg.Wait()

Common Mistakes

When coming from JavaScript, developers often make these mistakes:

  • Go goroutines are OS-scheduled; JS async is event-loop based
  • Go channels for communication; JS uses Promises and callbacks
  • Go can truly run code in parallel on multiple CPUs; JS is single-threaded
Common Pitfall
Don't assume Go works exactly like JavaScript. While the concepts may be similar, the syntax and behavior can differ significantly.

Key Takeaways

  • go keyword starts a goroutine (like fire-and-forget async)
  • Channels replace Promises for inter-goroutine communication
  • WaitGroup replaces Promise.all
  • Go is truly parallel; JS is single-threaded
Rule of Thumb
The best way to learn is by doing. Try rewriting some of your JavaScript code in Go to practice these concepts.
PreviousNext