Update tech_docs/go_getting_started.md
This commit is contained in:
@@ -1,3 +1,209 @@
|
||||
Certainly! Here's a concise guide to goroutines and channels in Go, covering all major points.
|
||||
|
||||
## Goroutines
|
||||
|
||||
Goroutines are lightweight threads managed by the Go runtime. They allow you to perform concurrent tasks without the overhead of traditional threads.
|
||||
|
||||
### Key Points
|
||||
|
||||
1. **Lightweight**: Goroutines are much lighter than OS threads, allowing you to run thousands of them simultaneously.
|
||||
2. **Easy to Use**: Creating a goroutine is as simple as adding the `go` keyword before a function call.
|
||||
3. **Automatic Scheduling**: The Go runtime schedules goroutines, making efficient use of system resources.
|
||||
|
||||
### Creating Goroutines
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
func say(s string) {
|
||||
for i := 0; i < 5; i++ {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
fmt.Println(s)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
go say("world") // This runs concurrently
|
||||
say("hello")
|
||||
}
|
||||
```
|
||||
|
||||
### Waiting for Goroutines
|
||||
|
||||
Using `sync.WaitGroup` to wait for goroutines to finish:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
)
|
||||
|
||||
func worker(id int, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
fmt.Printf("Worker %d starting\n", id)
|
||||
// Simulate work
|
||||
fmt.Printf("Worker %d done\n", id)
|
||||
}
|
||||
|
||||
func main() {
|
||||
var wg sync.WaitGroup
|
||||
|
||||
for i := 1; i <= 5; i++ {
|
||||
wg.Add(1)
|
||||
go worker(i, &wg)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
}
|
||||
```
|
||||
|
||||
### Best Practices
|
||||
|
||||
1. **Avoid Blocking**: Long-running or blocking operations should not be in the main goroutine.
|
||||
2. **Error Handling**: Properly handle errors within goroutines.
|
||||
3. **Resource Cleanup**: Ensure resources are properly cleaned up using `defer`.
|
||||
|
||||
## Channels
|
||||
|
||||
Channels provide a way for goroutines to communicate with each other and synchronize their execution.
|
||||
|
||||
### Key Points
|
||||
|
||||
1. **Typed**: Channels are typed conduits through which you can send and receive values of a specific type.
|
||||
2. **Safe**: Channels provide a safe way to share data between goroutines without explicit locks.
|
||||
3. **Directional**: Channels can be directional, meaning they can be restricted to send-only or receive-only.
|
||||
|
||||
### Creating Channels
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
messages := make(chan string)
|
||||
|
||||
go func() { messages <- "ping" }()
|
||||
|
||||
msg := <-messages
|
||||
fmt.Println(msg)
|
||||
}
|
||||
```
|
||||
|
||||
### Buffered Channels
|
||||
|
||||
Buffered channels allow you to specify the capacity of the channel.
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
messages := make(chan string, 2)
|
||||
|
||||
messages <- "buffered"
|
||||
messages <- "channel"
|
||||
|
||||
fmt.Println(<-messages)
|
||||
fmt.Println(<-messages)
|
||||
}
|
||||
```
|
||||
|
||||
### Channel Directions
|
||||
|
||||
You can specify if a channel is send-only or receive-only:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func sendMessage(ch chan<- string, msg string) {
|
||||
ch <- msg
|
||||
}
|
||||
|
||||
func receiveMessage(ch <-chan string) {
|
||||
fmt.Println(<-ch)
|
||||
}
|
||||
|
||||
func main() {
|
||||
ch := make(chan string)
|
||||
go sendMessage(ch, "hello")
|
||||
receiveMessage(ch)
|
||||
}
|
||||
```
|
||||
|
||||
### Select Statement
|
||||
|
||||
The `select` statement lets a goroutine wait on multiple communication operations.
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
ch1 := make(chan string)
|
||||
ch2 := make(chan string)
|
||||
|
||||
go func() {
|
||||
ch1 <- "message from ch1"
|
||||
}()
|
||||
|
||||
go func() {
|
||||
ch2 <- "message from ch2"
|
||||
}()
|
||||
|
||||
select {
|
||||
case msg1 := <-ch1:
|
||||
fmt.Println(msg1)
|
||||
case msg2 := <-ch2:
|
||||
fmt.Println(msg2)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Closing Channels
|
||||
|
||||
Closing a channel indicates that no more values will be sent on it.
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
ch := make(chan int)
|
||||
|
||||
go func() {
|
||||
for i := 0; i < 5; i++ {
|
||||
ch <- i
|
||||
}
|
||||
close(ch)
|
||||
}()
|
||||
|
||||
for v := range ch {
|
||||
fmt.Println(v)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Best Practices
|
||||
|
||||
1. **Avoid Deadlocks**: Ensure that channels are properly managed to avoid deadlocks.
|
||||
2. **Channel Capacity**: Use buffered channels when you need to decouple the timing between sending and receiving.
|
||||
3. **Closing Channels**: Close channels to signal completion of communication.
|
||||
|
||||
---
|
||||
|
||||
# Go (Golang) Comprehensive Guide
|
||||
|
||||
## Table of Contents
|
||||
|
||||
Reference in New Issue
Block a user