Горутина — это легковесный поток выполнения в Go, который:
Пример массового создания:
func main() {
for i := 0; i < 100000; i++ {
go func(num int) {
fmt.Println(num)
}(i)
}
time.Sleep(time.Second) // Даем время на выполнение
}
Запуск осуществляется через ключевое слово go
:
go function(arg1, arg2) // Асинхронный вызов функции
Горутины часто используют каналы для коммуникации:
func worker(jobs <-chan int, results chan<- int) {
for j := range jobs {
results <- j * 2
}
}
┌───────────┐ ┌───────────┐
│ P (P1) │ │ P (P2) │
├─────┬─────┤ ├─────┬─────┤
│ G1 │ G2 │ │ G3 │ G4 │
└─────┴─────┘ └─────┴─────┘
│ │
▼ ▼
┌───────────┐ ┌───────────┐
│ M (T1) │ │ M (T2) │
└───────────┘ └───────────┘
Используйте:
chan
)sync.WaitGroup
sync.Mutex
/RWMutex
для shared memoryПример с WaitGroup:
func main() {
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func(num int) {
defer wg.Done()
fmt.Println(num)
}(i)
}
wg.Wait() // Ожидаем завершения всех горутин
}
Типичные причины:
context.Context
для отменыХарактеристика | Горутина | Поток ОС |
---|---|---|
Стоимость создания | 200-700ns |
1-10µs |
Память (стартовая) | 2KB | 1-8MB |
Планировщик | Go runtime | ОС |
Переключение контекста | Дешевое (100ns ) |
Дорогое (1µs ) |
func processConcurrently(urls []string) []Result {
results := make([]Result, len(urls))
sem := make(chan struct{}, 10) // Ограничение 10 параллельных запросов
var wg sync.WaitGroup
for i, url := range urls {
wg.Add(1)
go func(idx int, u string) {
sem <- struct{}{} // Занимаем слот
defer func() {
<-sem // Освобождаем слот
wg.Done()
}()
// Выполняем работу
results[idx] = fetchData(u)
}(i, url)
}
wg.Wait()
return results
}
горутины — это фундаментальная абстракция параллелизма в Go, обеспечивающая эффективное использование ресурсов системы. Их легковесная природа позволяет создавать высоконагруженные concurrent-приложения с минимальными накладными расходами. Правильное использование горутин в сочетании с каналами и другими примитивами синхронизации — ключ к написанию производительного и надежного кода на Go.