Skip to content

Commit f5877bc

Browse files
committed
add
1 parent f823597 commit f5877bc

22 files changed

+6801
-46
lines changed
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
---
2+
title: 'Introduction to Concurrency in Go'
3+
slug: 'introduction-to-concurrency'
4+
---
5+
6+
# Introduction to Concurrency in Go
7+
8+
Concurrency is one of Go's most powerful features, but it's often misunderstood. Let's start by clarifying what concurrency actually means.
9+
10+
## Concurrency vs Parallelism
11+
12+
> Concurrency is not parallelism
13+
14+
Some quotes to support this statement:
15+
16+
> "Concurrency is a property of the code; parallelism is a property of the running program"
17+
18+
> "Concurrency is about dealing with lots of things at once. Parallelism is about doing lots of things at once."
19+
20+
Concurrency refers to the design pattern where multiple tasks can make progress independently, even if they're not executing simultaneously. Parallelism, on the other hand, is about executing multiple tasks simultaneously.
21+
22+
In Go, concurrency is built into the language design with three main components:
23+
24+
* **Concurrency execution (goroutines)** - Lightweight threads managed by the Go runtime
25+
* **Synchronization and messaging (channels)** - Safe communication between concurrent code
26+
* **Multi-way concurrent control (select)** - Coordination of multiple concurrent operations
27+
28+
## Why Go's Approach to Concurrency is Different
29+
30+
Go provides first-class support for concurrent code in a program, and channels solve the problem of communicating safely between concurrently running code.
31+
32+
Go also supports more traditional tools for writing concurrent code. Mutexes, pools, and locks are implemented in the sync package, but channels are often preferred for their simplicity and readability.
33+
34+
## Key Concurrency Features in Go
35+
36+
1. **Goroutines**: Lightweight threads that allow functions to run concurrently
37+
2. **Channels**: Communication pipes that allow goroutines to share data safely
38+
3. **Select Statement**: A control structure for handling multiple channel operations
39+
4. **WaitGroups**: A synchronization mechanism from the sync package
40+
5. **Mutex**: A way to protect shared data from concurrent access
41+
6. **Context Package**: Tools for cancellation, deadlines, and request-scoped values
42+
43+
In the following labs, we'll explore each of these features in depth and learn how to use them to write efficient concurrent programs.
44+
45+
## Summary
46+
47+
- Concurrency is about structure, parallelism is about execution
48+
- Go has built-in language features for concurrency
49+
- Go's approach favors communication over shared memory
50+
- Understanding concurrency patterns is essential for writing efficient Go programs
51+
52+
In the next lab, we'll dive deeper into channels, the fundamental communication mechanism in Go's concurrency model.
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
---
2+
title: 'Channels Basics'
3+
slug: 'channels-basics'
4+
---
5+
6+
# Channels Basics
7+
8+
Channels are one of the core features of Go's concurrency model. They provide a way for goroutines to communicate with each other and synchronize their execution.
9+
10+
## What are Channels?
11+
12+
Channels can be imagined as a pipe for streams of data. They are used to communicate information between goroutines. The fundamental philosophy in Go is:
13+
14+
> Don't communicate by sharing memory; share memory by communicating.
15+
16+
This means instead of using shared variables with locks, Go encourages passing data through channels.
17+
18+
## Creating a Channel
19+
20+
Creating a channel in Go is simple:
21+
22+
```go
23+
channel := make(chan interface{})
24+
```
25+
26+
This creates a channel that can send and receive values of any type (though it's usually better to use a specific type).
27+
28+
Here's a more typical example, creating a channel that handles string values:
29+
30+
```go
31+
messages := make(chan string)
32+
```
33+
34+
## Sending and Receiving
35+
36+
Channels use two primary operations:
37+
- The send operation `chan <-` sends a value into a channel
38+
- The receive operation `<-chan` receives a value from a channel
39+
40+
Let's see a simple example:
41+
42+
```go
43+
package main
44+
45+
import "fmt"
46+
47+
func main() {
48+
// Create a new channel
49+
messages := make(chan string)
50+
51+
// Send a value into the channel (in a separate goroutine)
52+
go func() {
53+
messages <- "ping"
54+
}()
55+
56+
// Receive the value from the channel
57+
msg := <-messages
58+
fmt.Println(msg)
59+
}
60+
```
61+
62+
When you run this program, you'll see the output:
63+
```
64+
ping
65+
```
66+
67+
## Channel Blocking
68+
69+
Channels are inherently blocking. This means:
70+
71+
1. A send operation `channel <- value` blocks until a receiver is ready to receive the value
72+
2. A receive operation `value := <-channel` blocks until a sender sends a value
73+
74+
This blocking behavior is what makes channels so powerful for synchronization between goroutines.
75+
76+
## Channel Types
77+
78+
There are different types of channels in Go:
79+
- **Bidirectional channels**: The default type, can be both read from and written to
80+
- **Directional channels**: Restricted to either sending or receiving
81+
- **Buffered channels**: Can hold a limited number of values without a receiver being ready
82+
83+
In the next labs, we'll explore each of these types in detail.
84+
85+
## When to Use Channels
86+
87+
Channels are ideal for:
88+
89+
1. Communicating between goroutines
90+
2. Signaling completion of tasks
91+
3. Distributing work among multiple goroutines
92+
4. Managing concurrency with timeouts and cancellation
93+
94+
## Summary
95+
96+
- Channels are a communication mechanism between goroutines
97+
- The syntax for creating a channel is `make(chan Type)`
98+
- Send values with `channel <- value`
99+
- Receive values with `value := <-channel`
100+
- Channels block until the operation can proceed
101+
- Channels provide built-in synchronization
102+
103+
In the next lab, we'll explore bidirectional channels in more detail.
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
---
2+
title: 'Bidirectional Channels'
3+
slug: 'bidirectional-channels'
4+
---
5+
6+
# Bidirectional Channels
7+
8+
By default, channels in Go are bidirectional, which means they can be used to both send and receive values. This is the simplest form of a channel and is what you get when you create a channel without any direction-specific notation.
9+
10+
## Creating a Bidirectional Channel
11+
12+
Creating a bidirectional channel is straightforward:
13+
14+
```go
15+
// Create a bidirectional channel for string values
16+
messages := make(chan string)
17+
```
18+
19+
## Using a Bidirectional Channel
20+
21+
Let's look at a simple example that demonstrates sending and receiving on a bidirectional channel:
22+
23+
```go
24+
package main
25+
26+
import "fmt"
27+
28+
func main() {
29+
messages := make(chan string)
30+
31+
// Send a value into the channel in a separate goroutine
32+
go func() {
33+
messages <- "ping"
34+
}()
35+
36+
// Receive the value from the channel
37+
msg := <-messages
38+
fmt.Println(msg)
39+
}
40+
```
41+
42+
In this example:
43+
1. We create a bidirectional channel called `messages`
44+
2. We launch a goroutine that sends the string "ping" into the channel
45+
3. The main goroutine receives the value from the channel
46+
4. The received value is printed
47+
48+
## Benefits and Limitations
49+
50+
**Benefits:**
51+
- Simple to use and understand
52+
- Flexible - can be used for both sending and receiving
53+
- No need to specify direction when creating the channel
54+
55+
**Limitations:**
56+
- Anyone can read and write to the channel
57+
- This can cause problems in concurrent environments where you want to restrict operations
58+
- No type safety to prevent incorrect usage
59+
60+
## When to Use Bidirectional Channels
61+
62+
Bidirectional channels are most appropriate when:
63+
64+
1. You have a simple communication pattern
65+
2. The same goroutine might need to both send and receive
66+
3. You're prototyping and don't need strict access control
67+
68+
## Common Patterns with Bidirectional Channels
69+
70+
### Ping-Pong Pattern
71+
72+
```go
73+
package main
74+
75+
import (
76+
"fmt"
77+
"time"
78+
)
79+
80+
func ping(ch chan string) {
81+
ch <- "ping"
82+
}
83+
84+
func pong(ch chan string) {
85+
msg := <-ch
86+
fmt.Println(msg)
87+
ch <- "pong"
88+
}
89+
90+
func main() {
91+
ch := make(chan string)
92+
93+
go ping(ch)
94+
go pong(ch)
95+
96+
fmt.Println(<-ch)
97+
time.Sleep(100 * time.Millisecond) // Ensure the goroutines have time to execute
98+
}
99+
```
100+
101+
### Basic Worker Pattern
102+
103+
```go
104+
package main
105+
106+
import "fmt"
107+
108+
func worker(jobs chan int, results chan int) {
109+
for job := range jobs {
110+
results <- job * 2 // Double the job value
111+
}
112+
}
113+
114+
func main() {
115+
jobs := make(chan int, 5)
116+
results := make(chan int, 5)
117+
118+
// Start a worker
119+
go worker(jobs, results)
120+
121+
// Send jobs
122+
for i := 1; i <= 3; i++ {
123+
jobs <- i
124+
}
125+
close(jobs)
126+
127+
// Collect results
128+
for i := 1; i <= 3; i++ {
129+
fmt.Println(<-results)
130+
}
131+
}
132+
```
133+
134+
## Summary
135+
136+
- Bidirectional channels can be used for both sending and receiving
137+
- They're created with `make(chan Type)`
138+
- They're the default channel type in Go
139+
- They offer flexibility but less type safety than directional channels
140+
- They're great for simple communication patterns
141+
142+
In the next lab, we'll look at directional channels, which add type safety by restricting operations to either sending or receiving.

0 commit comments

Comments
 (0)