Щоб пояснити концепції Go, такі як спільна пам'ять через канали (shared memory through channels), горутіни (goroutines) та коректне завершення роботи (graceful shutdown), можемо використати аналогію з "Kanjo другом🤑". Цей друг хоче насолоджуватись відпочинками з іншими, але не хоче витрачати забагато грошей. Щоб цього досягти, він збирає друзів для спільних вкладень, щоб усі могли розважатись за знижену ціну.
Давайте спочатку розглянемо код 😊
package main
import (
"fmt"
"sync"
"time"
)
func main() {
activities := []int{0, 50, 70, 0, 30, 10}
totalActivities := len(activities)
contributions := make(chan int, totalActivities)
stopFun := make(chan bool, 1) // Сигнал для зупинки веселощів
var wg sync.WaitGroup
fmt.Println("Драма з вкладеннями Kanjo друзів починається!!..")
// горутіни для кожного друга
for i, budget := range activities {
wg.Add(1)
go KanjoFriend(i+1, budget, contributions, stopFun, &wg)
}
go func() {
wg.Wait()
close(contributions)
close(stopFun)
}()
// Моніторинг, чи хтось не зупинить веселощі
funStopped := false
go func() {
for range stopFun {
funStopped = true
}
}()
// Збір всіх вкладень поки веселощі не зупиняться
totalFun := 0
for contribution := range contributions {
if funStopped {
fmt.Println("Веселощі були зупинені Kanjo другом! Вкладення припинено.")
break
}
totalFun += contribution
}
// Драматична пауза для напруги 😉
time.Sleep(time.Second)
fmt.Printf("Загальна сума зібраних коштів: %d\n", totalFun)
if funStopped {
fmt.Println("Kanjo друзі вирішили, що веселощі занадто дорогі, і все зупинили!")
} else {
fmt.Println("Kanjo друзі трохи сердиті, але всі внесли свій внесок і розважались разом!")
}
fmt.Println("Пам'ятайте: найкращі веселощі - це спільні веселощі, навіть якщо ви трохи Kanjo в серці..")
}
// KanjoFriend представляє економного друга, який або вносить свій внесок, або намагається розважатись безкоштовно
func KanjoFriend(id int, budget int, contributions chan<- int, stopFun chan<- bool, wg *sync.WaitGroup) {
defer wg.Done()
if budget == 0 {
// Kanjo друг дуже радий, коли не вносить вклад
fmt.Printf("Kanjo друг %d непомітно підкрадається і насолоджується веселощами БЕЗКОШТОВНО ....!!!!\n", id)
return
}
// Друзі неохоче вносять свій вклад
fmt.Printf("Друг %d неохоче вносить %d (але таємно бажає заощадити..).\n", id, budget)
// Якщо бюджет занадто великий, Kanjo друг може зупинити веселощі
if budget > 60 {
fmt.Printf("Kanjo друг %d кричить: 'СТОП! Ці веселощі стають занадто дорогими ..!!'\n", id)
stopFun <- true
return
}
contributions <- budget // Відправка внеску
time.Sleep(time.Millisecond * 100) // просто пауза для веселощів
}
output:-
Драма з вкладеннями Kanjo друзів починається!!..
Друг 2 неохоче вносить 50 (але таємно бажає заощадити..).
Друг 3 неохоче вносить 70 (але таємно бажає заощадити..).
Kanjo друг 3 кричить: 'СТОП! Ці веселощі стають занадто дорогими ..!!'
Друг 6 неохоче вносить 10 (але таємно бажає заощадити..).
Kanjo друг 1 непомітно підкрадається і насолоджується веселощами БЕЗКОШТОВНО ....!!!!
Друг 5 неохоче вносить 30 (але таємно бажає заощадити..).
Kanjo друг 4 непомітно підкрадається і насолоджується веселощами БЕЗКОШТОВНО ....!!!!
Веселощі були зупинені Kanjo другом! Вкладення припинено.
Загальна сума зібраних коштів: 50
Kanjo друзі вирішили, що веселощі занадто дорогі, і все зупинили!
Пам'ятайте: найкращі веселощі - це спільні веселощі, навіть якщо ви трохи Kanjo в серці..
- Go Спільна пам'ять через канали (Go Shared Memory Through Channels):
Замість прямого обміну пам'яттю (як у традиційних потоках), канали (channels) використовуються для комунікації між горутинами (goroutines). Це забезпечує безпечне виконання операцій без явних блокувань або м'ютексів.
Як це використовувалось у коді:
1.
Спільні дані через канали:
Канали contributions (Відправка вкладень до спільної пам'яті) і stopFun (Сигнал про зупинку веселощів) виконують роль спільних місць збереження пам'яті, в які горутіни надсилають або отримують дані.
contributions := make(chan int, totalActivities)
stopFun := make(chan bool, 1)
- Безпечне зчитування даних:
Головна рутина збирає дані з каналів безпечно, запобігаючи умовам гонки.
for contribution := range contributions {
if funStopped {
fmt.Println("Веселощі були зупинені Kanjo другом! Вкладення припинено.")
break
}
totalFun += contribution // Безпечне зчитування даних
}
2. Горутіни (Goroutines):-
Горутіни — це легковажні потоки, якими керує середовище виконання Go, що дозволяє одночасно виконувати завдання.
Як це використовується в коді:
Горутіни виконуються незалежно, дозволяючи кільком друзям діяти одночасно, не блокуючи один одного.
Логіка кожного друга (внесок чи зупинка веселощів) виконується у своїй власній горутині.
go KanjoFriend(i+1, budget, contributions, stopFun, &wg)go
3. Коректне завершення роботи (Graceful Shutdown):-
Коректне завершення роботи гарантує, що всі ресурси (наприклад, горутіни і канали) будуть належно очищені, коли програма завершується або коли отримано сигнал про переривання (наприклад, stopFun).
Як це використовується в коді:
- sync.WaitGroup гарантує, що всі горутіни завершать свої завдання перед тим, як перейти до наступного кроку.
wg.Add(1)
defer wg.Done()
wg.Wait()
- Канали (contributions, stopFun) закриваються після завершення всіх горутин.
go func() {
wg.Wait()
close(contributions)
close(stopFun)
}()go
- Канал stopFun посилає сигнал, коли друг вирішує, що веселощі занадто дорогі. Головна рутина зупиняє подальші вкладення після отримання цього сигналу.
if funStopped {
fmt.Println("Kanjo друзі вирішили, що веселощі занадто дорогі, і все зупинили!")
} else {
fmt.Println("Kanjo друзі трохи сердиті, але всі внесли свій внесок і розважались разом!")
}
Підсумовуючи, Ефективне управління ресурсами через канали забезпечує безпечний доступ до спільної пам'яті, а горутіни надають можливість виконувати завдання одночасно без накладних витрат традиційних потоків. Коректне завершення роботи гарантує, що програма правильно обробляє ресурси, навіть під час переривань, зберігаючи надійність. Такий підхід ефективно масштабується, дозволяючи обробляти велику кількість одночасних завдань.
Наступного разу, коли зустрінете канжо друга, не сприймайте це неправильно. Натомість, вважайте його своїм рятівником, який виводить вас із ситуацій переплат, подібно до GOLANG 😅.
Перекладено з: Kanjos Friend and His Free-Fun Strategy