Ответ
Ключевая особенность Go — это встроенная модель конкурентности (concurrency), основанная на горутинах (goroutines) и каналах (channels).
Это не просто синтаксический сахар, а фундаментальная часть языка, которая позволяет писать высокопроизводительные конкурентные программы просто и безопасно.
1. Горутины (Goroutines):
- Это легковесные потоки, управляемые средой выполнения Go, а не операционной системой.
- Их стек изначально очень мал (около 2 КБ) и может расти по мере необходимости. Можно легко запустить сотни тысяч и даже миллионы горутин одновременно.
- Запускаются с помощью простого ключевого слова
go
.
2. Каналы (Channels):
- Это типизированные "трубы", через которые горутины могут безопасно обмениваться данными, не прибегая к традиционным блокировкам (мьютексам).
- Они реализуют философию Go: "Do not communicate by sharing memory; instead, share memory by communicating." (Не общайтесь, разделяя память; вместо этого разделяйте память, общаясь).
Пример: Worker Pool
Этот код создает пул из 3-х воркеров, которые конкурентно обрабатывают задачи из канала jobs
и отправляют результаты в канал results
.
package main
import (
"fmt"
"time"
)
// worker получает задачи из канала jobs и отправляет результат в results
func worker(id int, jobs <-chan int, results chan<- int) {
for j := range jobs {
fmt.Printf("worker %d started job %dn", id, j)
time.Sleep(time.Second) // Имитация работы
results <- j * 2
fmt.Printf("worker %d finished job %dn", id, j)
}
}
func main() {
const numJobs = 5
jobs := make(chan int, numJobs)
results := make(chan int, numJobs)
// Запускаем 3 воркера
for w := 1; w <= 3; w++ {
go worker(w, jobs, results)
}
// Отправляем 5 задач в канал jobs
for j := 1; j <= numJobs; j++ {
jobs <- j
}
close(jobs) // Закрываем канал, чтобы воркеры завершились после выполнения всех задач
// Собираем результаты
for a := 1; a <= numJobs; a++ {
<-results
}
}