eFusion 23 мая 2021

πŸƒ ΠŸΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½ΠΎΠ΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ Π² Go

Π˜Π·ΡƒΡ‡Π°Π΅ΠΌ основы ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½ΠΎΠ³ΠΎ программирования Π² Go, Π° Ρ‚Π°ΠΊΠΆΠ΅ пытаСмся Ρ€Π°Π·ΠΎΠ±Ρ€Π°Ρ‚ΡŒΡΡ Π½Π° ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°Ρ…, ΠΏΠΎΡ‡Π΅ΠΌΡƒ ΠΊΠΎΠ½ΠΊΡƒΡ€Π΅Π½Ρ‚Π½ΠΎΡΡ‚ΡŒ Π² Go – это Π½Π΅ совсСм ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΠΈΠ·ΠΌ.
πŸƒ ΠŸΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½ΠΎΠ΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ Π² Go

ΠŸΠ΅Ρ€Π΅Π²ΠΎΠ΄ публикуСтся с сокращСниями, Π°Π²Ρ‚ΠΎΡ€ ΠΎΡ€ΠΈΠ³ΠΈΠ½Π°Π»ΡŒΠ½ΠΎΠΉ ΡΡ‚Π°Ρ‚ΡŒΠΈ Stefan Nilsson.

Для Π½Π°Ρ‡Π°Π»Π° Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Ρ€Π°Π·ΠΎΠ±Ρ€Π°Ρ‚ΡŒΡΡ, ΠΊΠ°ΠΊ ΠΏΠΈΡΠ°Ρ‚ΡŒ Π±Π°Π·ΠΎΠ²Ρ‹Π΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ Π½Π° Go. ОсвСТим знания, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΠΎΠΌΠΎΡ‡ΡŒ сСбС быстрСС ΠΎΡΠ²ΠΎΠΈΡ‚ΡŒΡΡ.

ΠžΡΠ½ΠΎΠ²Ρ‹

The Go Playground – ΠΈΠ½Ρ‚Π΅Ρ€Π°ΠΊΡ‚ΠΈΠ²Π½Ρ‹ΠΉ Π²Π΅Π±-сСрвис, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ позволяСт Π·Π°ΠΏΡƒΡΠΊΠ°Ρ‚ΡŒ Π² пСсочницС нСбольшиС ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ Π² Π΄ΡƒΡ…Π΅ Β«Hello world!Β». ΠŸΠΎΠΏΡ€ΠΎΠ±ΡƒΠΉΡ‚Π΅!

        package main

import "fmt"

func main() {
    fmt.Println("Hello, world!")
}
    

Π˜Π·ΡƒΡ‡ΠΈΡ‚Π΅ основы Go

A Tour of Go – Π΅Ρ‰Π΅ ΠΎΠ΄ΠΈΠ½ ΠΈΠ½Ρ‚Π΅Ρ€Π°ΠΊΡ‚ΠΈΠ²Π½Ρ‹ΠΉ ΡƒΡ‡Π΅Π±Π½ΠΈΠΊ с ΠΊΡƒΡ‡Π΅ΠΉ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ΠΎΠ². Он Π±Π΅Ρ€Π΅Ρ‚ Π½Π°Ρ‡Π°Π»ΠΎ Π½Π° ΠΎΡ„ΠΈΡ†ΠΈΠ°Π»ΡŒΠ½ΠΎΠΌ сайтС ΠΈ ΠΎΠ±ΡƒΡ‡Π°Π΅Ρ‚ вас основам программирования Go Π² Π±Ρ€Π°ΡƒΠ·Π΅Ρ€Π΅.

УстановитС инструмСнты Go

Π’ Getting Started ΠΎΠ±ΡŠΡΡΠ½ΡΠ΅Ρ‚ΡΡ, ΠΊΠ°ΠΊ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ инструмСнты Go. Доступны Π±ΠΈΠ½Π°Ρ€Π½Ρ‹Π΅ ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹ для FreeBSD, Linux, Mac OS X ΠΈ Windows, Π° Ρ‚Π°ΠΊΠΆΠ΅ инструкции ΠΏΠΎ Ρ€Π°Π·Π²Π΅Ρ€Ρ‚Ρ‹Π²Π°Π½ΠΈΡŽ ΠΈ настройкС.

НачнитС ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ Go

How to Write Go Code посвящСн Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ΅ простых ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² Go. Он рассказываСт ΠΏΡ€ΠΎ ΠΎΡ€Π³Π°Π½ΠΈΠ·Π°Ρ†ΠΈΡŽ ΠΈ тСстированиС ΠΊΠΎΠ΄Π°, Π° Ρ‚Π°ΠΊΠΆΠ΅ ΠΏΡ€ΠΎ использованиС ΠΊΠΎΠΌΠ°Π½Π΄ fetch, build ΠΈ install.

Π“ΠΎΡ€ΡƒΡ‚ΠΈΠ½Ρ‹

Π’Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ Π½ΠΎΠ²Ρ‹ΠΉ ΠΏΠΎΡ‚ΠΎΠΊ (Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Ρƒ) с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€Π° go. ВсС Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Ρ‹ Π² ΠΎΠ΄Π½ΠΎΠΉ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ ΠΎΠ΄Π½ΠΎ ΠΈ Ρ‚ΠΎ ΠΆΠ΅ адрСсноС пространство.

        go list.Sort() //запускаСтся list.Sort ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½ΠΎ, Π±Π΅Π· оТидания
    

ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° Π²Ρ‹Π²ΠΎΠ΄ΠΈΡ‚ сообщСниС Β«Hello from main goroutineΒ». Она Ρ‚Π°ΠΊΠΆΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π½Π°ΠΏΠ΅Ρ‡Π°Ρ‚Π°Ρ‚ΡŒ Β«Hello from another goroutineΒ», Π² зависимости ΠΎΡ‚ Ρ‚ΠΎΠ³ΠΎ, какая ΠΈΠ· Π΄Π²ΡƒΡ… Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½ Π·Π°Π²Π΅Ρ€ΡˆΠΈΡ‚ΡΡ ΠΏΠ΅Ρ€Π²ΠΎΠΉ.

        func main() {
    go fmt.Println("Hello from another goroutine")
    fmt.Println("Hello from main goroutine")

    // Π’ этот ΠΌΠΎΠΌΠ΅Π½Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ останавливаСтся ΠΈ ΡƒΠ±ΠΈΠ²Π°ΡŽΡ‚ΡΡ всС
    // Π°ΠΊΡ‚ΠΈΠ²Π½Ρ‹Π΅ Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Ρ‹
}
    

Π‘Π»Π΅Π΄ΡƒΡŽΡ‰Π°Ρ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° скорСС всСго Π²Ρ‹Π²Π΅Π΄Π΅Ρ‚ Β«Hello from main goroutineΒ» ΠΈ Β«Hello from another goroutineΒ». Они ΠΌΠΎΠ³ΡƒΡ‚ ΠΏΠΎΡΠ²ΠΈΡ‚ΡŒΡΡ Π² любом порядкС. Π•Ρ‰Π΅ ΠΎΠ΄Π½Π° ΠΎΡΠΎΠ±Π΅Π½Π½ΠΎΡΡ‚ΡŒ Π·Π°ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ вторая Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Π° Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ ΠΎΡ‡Π΅Π½ΡŒ ΠΌΠ΅Π΄Π»Π΅Π½Π½ΠΎ ΠΈ Π½Π΅ ΠΏΠ΅Ρ‡Π°Ρ‚Π°Π΅Ρ‚ сообщСниС Π΄ΠΎ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹.

        func main() {
    go fmt.Println("Hello from another goroutine")
    fmt.Println("Hello from main goroutine")

    time.Sleep(time.Second) // Π΄Π°Π΄ΠΈΠΌ Π΄Ρ€ΡƒΠ³ΠΎΠΉ Π³ΠΎΡ€ΠΎΡƒΡ‚ΠΈΠ½Π΅ врСмя Π·Π°Π²Π΅Ρ€ΡˆΠΈΡ‚ΡŒΡΡ
}
    

Π’ΠΎΡ‚ Π±ΠΎΠ»Π΅Π΅ рСалистичный ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Π³Π΄Π΅ опрСдСляСтся функция, которая ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ concurrency для отсрочки события:

        // Publish ΠΏΠ΅Ρ‡Π°Ρ‚Π°Π΅Ρ‚ тСкст Π² stdout ΠΏΠΎ истСчСнии Π·Π°Π΄Π°Π½Π½ΠΎΠ³ΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ.
// Он Π½Π΅ блокируСтся ΠΈ сразу ΠΆΠ΅ возвращаСтся.
func Publish(text string, delay time.Duration) {
    go func() {
        time.Sleep(delay)
        fmt.Println("BREAKING NEWS:", text)
    }() // ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ Π½Π° ΠΊΡ€ΡƒΠ³Π»Ρ‹Π΅ скобки. ΠœΡ‹ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ 
        // Π°Π½ΠΎΠ½ΠΈΠΌΠ½ΡƒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ.
}
    

Π’ΠΎΡ‚ ΠΊΠ°ΠΊ Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ Publish:

        func main() {
    Publish("A goroutine starts a new thread.", 5*time.Second)
    fmt.Println("Let’s hope the news will published before I leave.")

    // ДоТидаСмся ΠΏΡƒΠ±Π»ΠΈΠΊΠ°Ρ†ΠΈΠΈ новостСй
    time.Sleep(10 * time.Second)

    fmt.Println("Ten seconds later: I’m leaving now.")
}
    

Π‘ΠΊΠΎΡ€Π΅Π΅ всСго ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° Π½Π°ΠΏΠ΅Ρ‡Π°Ρ‚Π°Π΅Ρ‚ Ρ‚Ρ€ΠΈ строки Π² Π·Π°Π΄Π°Π½Π½ΠΎΠΌ порядкС с пятисСкундными ΠΏΠ΅Ρ€Π΅Ρ€Ρ‹Π²Π°ΠΌΠΈ ΠΌΠ΅ΠΆΠ΄Ρƒ Π½ΠΈΠΌΠΈ.

        $ go run publish1.go
Let’s hope the news will published before I leave.
BREAKING NEWS: A goroutine starts a new thread.
Ten seconds later: I’m leaving now.
    

НСвозмоТно Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΠ΅ ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² Π² процСссС «сна», Π½ΠΎ Π΅ΡΡ‚ΡŒ ΠΌΠ΅Ρ‚ΠΎΠ΄ синхронизации – использованиС ΠΊΠ°Π½Π°Π»ΠΎΠ².

РСализация

Π“ΠΎΡ€ΡƒΡ‚ΠΈΠ½Ρ‹ ΠΈΠΌΠ΅ΡŽΡ‚ нСбольшой вСс ΠΈ стоят Π½Π΅ΠΌΠ½ΠΎΠ³ΠΈΠΌ большС, Ρ‡Π΅ΠΌ Π²Ρ‹Π΄Π΅Π»Π΅Π½ΠΈΠ΅ мСста Π² стСкС. ΠœΠ΅ΡΡ‚ΠΎ Π² ΠΊΡƒΡ‡Π΅ выдСляСтся ΠΈ освобоТдаСтся ΠΏΠΎ ΠΌΠ΅Ρ€Π΅ нСобходимости.

Π’Π½ΡƒΡ‚Ρ€ΠΈ Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Ρ‹ Π΄Π΅ΠΉΡΡ‚Π²ΡƒΡŽΡ‚ ΠΊΠ°ΠΊ ΠΊΠΎΡ€ΡƒΡ‚ΠΈΠ½Ρ‹, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΌΡƒΠ»ΡŒΡ‚ΠΈΠΏΠ»Π΅ΠΊΡΠΈΡ€ΡƒΡŽΡ‚ΡΡ ΠΌΠ΅ΠΆΠ΄Ρƒ нСсколькими ΠΏΠΎΡ‚ΠΎΠΊΠ°ΠΌΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΎΠ½Π½ΠΎΠΉ систСмы. Если ΠΎΠ΄Π½Π° Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Π° Π±Π»ΠΎΠΊΠΈΡ€ΡƒΠ΅Ρ‚ ΠΏΠΎΡ‚ΠΎΠΊ ОБ, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, оТидая Π²Π²ΠΎΠ΄Π°, Π΄Ρ€ΡƒΠ³ΠΈΠ΅ Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Ρ‹ Π² этом ΠΏΠΎΡ‚ΠΎΠΊΠ΅ Π±ΡƒΠ΄ΡƒΡ‚ ΠΌΠΈΠ³Ρ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΡ€ΠΎΠ΄ΠΎΠ»ΠΆΠ°Ρ‚ΡŒ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ.

ΠšΠ°Π½Π°Π»Ρ‹ ΠΎΠ±Π΅ΡΠΏΠ΅Ρ‡ΠΈΠ²Π°ΡŽΡ‚ ΡΠΈΠ½Ρ…Ρ€ΠΎΠ½ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½ΡƒΡŽ связь

ΠšΠ°Π½Π°Π»Ρ‹ – это ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ, с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Ρ‹ ΡΠΈΠ½Ρ…Ρ€ΠΎΠ½ΠΈΠ·ΠΈΡ€ΡƒΡŽΡ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΈ ΠΎΠ±ΠΌΠ΅Π½ΠΈΠ²Π°ΡŽΡ‚ΡΡ Π΄Π°Π½Π½Ρ‹ΠΌΠΈ, пСрСдавая значСния.

НовоС Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΊΠ°Π½Π°Π»Π° ΠΌΠΎΠΆΠ½ΠΎ Π·Π°Π΄Π°Ρ‚ΡŒ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ встроСнной Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ make.

        // Π½Π΅Π±ΡƒΡ„Π΅Ρ€ΠΈΠ·ΠΎΠ²Π°Π½Π½Ρ‹ΠΉ ΠΊΠ°Π½Π°Π» int-ΠΎΠ²
ic := make(chan int)

// Π±ΡƒΡ„Π΅Ρ€ΠΈΠ·ΠΎΠ²Π°Π½Π½Ρ‹ΠΉ ΠΊΠ°Π½Π°Π» Π½Π° 10 строк
sc := make(chan string, 10)
    

Π§Ρ‚ΠΎΠ±Ρ‹ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΈΡ‚ΡŒ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Π² ΠΊΠ°Π½Π°Π», ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ Π±ΠΈΠ½Π°Ρ€Π½Ρ‹ΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ Β«<-Β», Π° для получСния – ΡƒΠ½Π°Ρ€Π½Ρ‹ΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€.

        ic <- 3   // отправляСм 3 Π² ΠΊΠ°Π½Π°Π»
n := <-sc // ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ строку ΠΈΠ· ΠΊΠ°Π½Π°Π»Π°
    

ΠžΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ Π·Π°Π΄Π°Π΅Ρ‚ Π½Π°ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ ΠΊΠ°Π½Π°Π»Π° Π½Π° ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΡƒ ΠΈΠ»ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅. По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ ΠΊΠ°Π½Π°Π» являСтся Π΄Π²ΡƒΠ½Π°ΠΏΡ€Π°Π²Π»Π΅Π½Π½Ρ‹ΠΌ.

        chan Sushi    // ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ для ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠΈ ΠΈ получСния Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ Ρ‚ΠΈΠΏΠ° Sushi
chan<- string // ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ для ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠΈ строк
<-chan int    // ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ для получСния int
    

Π‘ΡƒΡ„Π΅Ρ€ΠΈΠ·ΠΎΠ²Π°Π½Π½Ρ‹Π΅ ΠΈ Π½Π΅Π±ΡƒΡ„Π΅Ρ€ΠΈΠ·ΠΎΠ²Π°Π½Π½Ρ‹Π΅ ΠΊΠ°Π½Π°Π»Ρ‹

  • Если пропускная ΡΠΏΠΎΡΠΎΠ±Π½ΠΎΡΡ‚ΡŒ ΠΊΠ°Π½Π°Π»Π° Ρ€Π°Π²Π½Π° Π½ΡƒΠ»ΡŽ ΠΈΠ»ΠΈ отсутствуСт, ΠΊΠ°Π½Π°Π» Π½Π΅ буфСризуСтся ΠΈ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΈΡ‚Π΅Π»ΡŒ блокируСтся Π΄ΠΎ Ρ‚Π΅Ρ… ΠΏΠΎΡ€, ΠΏΠΎΠΊΠ° ΠΏΠΎΠ»ΡƒΡ‡Π°Ρ‚Π΅Π»ΡŒ Π½Π΅ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅.
  • Если ΠΊΠ°Π½Π°Π» ΠΈΠΌΠ΅Π΅Ρ‚ Π±ΡƒΡ„Π΅Ρ€, ΠΎΡ‚ΠΏΡ€Π°Π²ΠΈΡ‚Π΅Π»ΡŒ блокируСтся Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π΄ΠΎ Ρ‚Π΅Ρ… ΠΏΠΎΡ€, ΠΏΠΎΠΊΠ° Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ скопировано Π² Π±ΡƒΡ„Π΅Ρ€. Если Π±ΡƒΡ„Π΅Ρ€ Π·Π°ΠΏΠΎΠ»Π½Π΅Π½, ΠΆΠ΄Π΅ΠΌ ΠΏΠΎΠΊΠ° ΠΊΠ°ΠΊΠΎΠΉ-Π»ΠΈΠ±ΠΎ ΠΏΠΎΠ»ΡƒΡ‡Π°Ρ‚Π΅Π»ΡŒ Π½Π΅ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅.
  • ΠŸΡ€ΠΈΠ΅ΠΌΠ½ΠΈΠΊΠΈ всСгда Π±Π»ΠΎΠΊΠΈΡ€ΡƒΡŽΡ‚ΡΡ, ΠΏΠΎΠΊΠ° Π½Π΅ появятся Π΄Π°Π½Π½Ρ‹Π΅ для ΠΏΡ€ΠΈΠ΅ΠΌΠ°.
  • ΠžΡ‚ΠΏΡ€Π°Π²ΠΊΠ° ΠΈΠ»ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ с nil-ΠΊΠ°Π½Π°Π»Π° блокируСтся навсСгда.

Π—Π°ΠΊΡ€Ρ‹Ρ‚ΠΈΠ΅ ΠΊΠ°Π½Π°Π»Π°

Ѐункция закрытия ΠΏΠΎΠΌΠ΅Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ Π½ΠΈΠΊΠ°ΠΊΠΈΠ΅ значСния большС Π½Π΅ Π±ΡƒΠ΄ΡƒΡ‚ ΠΎΡ‚ΠΏΡ€Π°Π²Π»ΡΡ‚ΡŒΡΡ ΠΏΠΎ ΠΊΠ°Π½Π°Π»Ρƒ. ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, Ρ‡Ρ‚ΠΎ Π·Π°ΠΊΡ€Ρ‹Π²Π°Ρ‚ΡŒ ΠΊΠ°Π½Π°Π» Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π² Ρ‚ΠΎΠΌ случаС, Ссли ΠΏΡ€ΠΈΠ΅ΠΌΠ½ΠΈΠΊ этого ΠΎΠΆΠΈΠ΄Π°Π΅Ρ‚.

  • ПослС Π²Ρ‹Π·ΠΎΠ²Π° close ΠΈ послС получСния Π»ΡŽΠ±Ρ‹Ρ… Ρ€Π°Π½Π΅Π΅ ΠΎΡ‚ΠΏΡ€Π°Π²Π»Π΅Π½Π½Ρ‹Ρ… Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ, ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΏΡ€ΠΈΠ΅ΠΌΠ° Π²Π΅Ρ€Π½ΡƒΡ‚ Π½ΡƒΠ»Π΅Π²ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Π±Π΅Π· Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ.
  • ΠžΠΏΠ΅Ρ€Π°Ρ†ΠΈΡ ΠΏΡ€ΠΈΠ΅ΠΌΠ° мноТСства Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ состояниС ΠΊΠ°Π½Π°Π»Π°.
  • ΠžΡ‚ΠΏΡ€Π°Π²ΠΊΠ° Π² Π·Π°ΠΊΡ€Ρ‹Ρ‚Ρ‹ΠΉ ΠΊΠ°Π½Π°Π» ΠΈΠ»ΠΈ Π΅Π³ΠΎ Π·Π°ΠΊΡ€Ρ‹Ρ‚ΠΈΠ΅, Π° Ρ‚Π°ΠΊΠΆΠ΅ Π·Π°ΠΊΡ€Ρ‹Ρ‚ΠΈΠ΅ nil-ΠΊΠ°Π½Π°Π»Π°, Π²Ρ‹Π·ΠΎΠ²ΡƒΡ‚ run-time panic.
        ch := make(chan string)
go func() {
    ch <- "Hello!"
    close(ch)
}()

fmt.Println(<-ch) // Π½Π°ΠΏΠ΅Ρ‡Π°Ρ‚Π°Π΅Ρ‚ Β«Hello!Β»
fmt.Println(<-ch) // Π²Ρ‹Π²Π΅Π΄Π΅Ρ‚ Π½ΡƒΠ»Π΅Π²ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ «» Π±Π΅Π· Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ
fmt.Println(<-ch) // Π΅Ρ‰Π΅ Ρ€Π°Π· Π½Π°ΠΏΠ΅Ρ‡Π°Ρ‚Π°Π΅Ρ‚ «»
v, ok := <-ch     // v - это «», ok – false

// ΠΏΠΎΠ»ΡƒΡ‡Π°Ρ‚ΡŒ значСния ΠΎΡ‚ ch Π΄ΠΎ закрытия
for v := range ch {
    fmt.Println(v) // Π½Π΅ выполнится
}
    

ΠŸΡ€ΠΈΠΌΠ΅Ρ€

Π’ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΌ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ функция Publish Π²Π΅Ρ€Π½Π΅Ρ‚ ΠΊΠ°Π½Π°Π», ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ для броадкастинга сообщСния послС ΠΏΡƒΠ±Π»ΠΈΠΊΠ°Ρ†ΠΈΠΈ тСкста:

        // Publish Π½Π°ΠΏΠ΅Ρ‡Π°Ρ‚Π°Π΅Ρ‚ тСкст Π² stdout ΠΏΠΎ истСчСнии Π·Π°Π΄Π°Π½Π½ΠΎΠ³ΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ.
// Когда тСкст Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠΏΡƒΠ±Π»ΠΈΠΊΠΎΠ²Π°Π½, Π·Π°ΠΊΡ€Ρ‹Π²Π°Π΅ΠΌ ΠΊΠ°Π½Π°Π», ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π½Π° Β«ΠΏΠ°ΡƒΠ·Π΅Β».
func Publish(text string, delay time.Duration) (wait <-chan struct{}) {
	ch := make(chan struct{})
	go func() {
		time.Sleep(delay)
		fmt.Println(text)
		close(ch)
	}()
	return ch
}
    

ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅: ΠΌΡ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ ΠΊΠ°Π½Π°Π» пустых структур для указания, Ρ‡Ρ‚ΠΎ ΠΊΠ°Π½Π°Π» Π±ΡƒΠ΄Π΅Ρ‚ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ для сигнализации, Π° Π½Π΅ для ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ Π΄Π°Π½Π½Ρ‹Ρ…. Выглядит это Ρ‚Π°ΠΊ:

        wait := Publish("important news", 2 * time.Minute)
// Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΠΌ Ρ‡Ρ‚ΠΎ-Π½ΠΈΠ±ΡƒΠ΄ΡŒ
<-wait // Π² Π±Π»ΠΎΠΊΠ΅, ΠΏΠΎΠΊΠ° тСкст Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠΏΡƒΠ±Π»ΠΈΠΊΠΎΠ²Π°Π½
    

Select ΠΎΠΆΠΈΠ΄Π°Π΅Ρ‚ Π³Ρ€ΡƒΠΏΠΏΡ‹ ΠΊΠ°Π½Π°Π»ΠΎΠ²

ΠžΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ select ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ ΠΎΠΆΠΈΠ΄Π°Π΅Ρ‚ Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠΈ ΠΈΠ»ΠΈ получСния.

  • ΠžΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ блокируСтся Π΄ΠΎ Ρ‚Π΅Ρ… ΠΏΠΎΡ€, ΠΏΠΎΠΊΠ° ΠΎΠ΄Π½Π° ΠΈΠ· ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ Ρ€Π°Π·Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½Π°.
  • Если выполняСтся нСсколько ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ, Ρ‚ΠΎ ΠΎΠ΄Π½Π° ΠΈΠ· Π½ΠΈΡ… Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π±Ρ€Π°Π½Π° случайным ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ.
        // блокируСтся Π΄ΠΎ Ρ‚Π΅Ρ… ΠΏΠΎΡ€, ΠΏΠΎΠΊΠ° Π΄Π°Π½Π½Ρ‹Π΅ Π½Π΅ появятся Π² ch1 ΠΈΠ»ΠΈ ch2
select {
case <-ch1:
    fmt.Println("Received from ch1")
case <-ch2:
    fmt.Println("Received from ch2")
}
    

ΠžΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠΈ ΠΈ ΠΏΡ€ΠΈΠ΅ΠΌΠ° Π² nil-ΠΊΠ°Π½Π°Π»Π΅ Π±Π»ΠΎΠΊΠΈΡ€ΡƒΡŽΡ‚ΡΡ навсСгда. Π­Ρ‚ΠΎ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ для ΠΎΡ‚ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ ΠΊΠ°Π½Π°Π»Π° Π² инструкции select:

        ch1 = nil // ΠΎΡ‚ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ этот ΠΊΠ°Π½Π°Π»
select {
case <-ch1:
    fmt.Println("Received from ch1") // Π½Π΅ ΠΏΡ€ΠΎΠΈΠ·ΠΎΠΉΠ΄Π΅Ρ‚
case <-ch2:
    fmt.Println("Received from ch2")
}
    

Π’Π°Ρ€ΠΈΠ°Π½Ρ‚ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ

Π’Π°Ρ€ΠΈΠ°Π½Ρ‚ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½, Ссли всС ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹Π΅ Π·Π°Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½Ρ‹.

        // Π½ΠΈΠΊΠΎΠ³Π΄Π° Π½Π΅ заблокируСтся
select {
case x := <-ch:
    fmt.Println("Received", x)
default:
    fmt.Println("Nothing available")
}
    

ΠŸΡ€ΠΈΠΌΠ΅Ρ€Ρ‹

БСсконСчная случайная двоичная ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ

Π’ качСствС ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ случайный Π²Ρ‹Π±ΠΎΡ€ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚ΠΎΠ², ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΌΠΎΠ³ΡƒΡ‚ Π³Π΅Π½Π΅Ρ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ случайныС Π±ΠΈΡ‚Ρ‹.

        rand := make(chan int)
for {
    select {
    case rand <- 0: // no statement
    case rand <- 1:
    }
}
    

ΠžΠΏΠ΅Ρ€Π°Ρ†ΠΈΡ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ ΠΏΠΎ Ρ‚Π°ΠΉΠΌΠ°ΡƒΡ‚Ρƒ

Ѐункция time.After Π²Ρ…ΠΎΠ΄ΠΈΡ‚ Π² ΡΡ‚Π°Π½Π΄Π°Ρ€Ρ‚Π½ΡƒΡŽ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΡƒ. Она ΠΎΠΆΠΈΠ΄Π°Π΅Ρ‚ истСчСния ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠ³ΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ, Π° Π·Π°Ρ‚Π΅ΠΌ отправляСт Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π΅ врСмя Π² Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΡ‹ΠΉ ΠΊΠ°Π½Π°Π»:

        select {
case news := <-AFP:
    fmt.Println(news)
case <-time.After(time.Minute):
    fmt.Println("Time out: No news in one minute")
}
    

ΠžΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ select блокируСтся Π΄ΠΎ Ρ‚Π΅Ρ… ΠΏΠΎΡ€, ΠΏΠΎΠΊΠ° ΠΏΠΎ ΠΊΡ€Π°ΠΉΠ½Π΅ΠΉ ΠΌΠ΅Ρ€Π΅ ΠΎΠ΄ΠΈΠ½ case Π½Π΅ смоТСт Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒΡΡ. Π‘ Π½ΡƒΠ»Π΅Π²Ρ‹ΠΌΠΈ кСйсами этого Π½ΠΈΠΊΠΎΠ³Π΄Π° Π½Π΅ ΠΏΡ€ΠΎΠΈΠ·ΠΎΠΉΠ΄Π΅Ρ‚:

        select {}
    

Π“ΠΎΠ½ΠΊΠΈ Π΄Π°Π½Π½Ρ‹Ρ…

Π“ΠΎΠ½ΠΊΠ° Π΄Π°Π½Π½Ρ‹Ρ… происходит, ΠΊΠΎΠ³Π΄Π° Π΄Π²Π΅ Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Ρ‹ ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ ΠΎΠ±Ρ€Π°Ρ‰Π°ΡŽΡ‚ΡΡ ΠΊ ΠΎΠ΄Π½ΠΎΠΉ ΠΈ Ρ‚ΠΎΠΉ ΠΆΠ΅ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ ΠΈ хотя Π±Ρ‹ ΠΎΠ΄Π½ΠΎ ΠΈΠ· ΠΎΠ±Ρ€Π°Ρ‰Π΅Π½ΠΈΠ΅ являСтся записью.

Вакая ситуация Π²ΠΎΠ·Π½ΠΈΠΊΠ°Π΅Ρ‚ часто ΠΈ ΠΌΠΎΠΆΠ΅Ρ‚ ΡƒΡΠ»ΠΎΠΆΠ½ΠΈΡ‚ΡŒ ΠΎΡ‚Π»Π°Π΄ΠΊΡƒ.

Показанная Π½ΠΈΠΆΠ΅ функция ΠΏΡ€ΠΈΠ²ΠΎΠ΄ΠΈΡ‚ ΠΊ Π³ΠΎΠ½ΠΊΠ΅ Π΄Π°Π½Π½Ρ‹Ρ…, ΠΈ Π΅Π΅ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ Π½Π΅ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΎ – ΠΎΠ½Π° ΠΌΠΎΠΆΠ΅Ρ‚, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Π½Π°ΠΏΠ΅Ρ‡Π°Ρ‚Π°Ρ‚ΡŒ число 1. ΠŸΠΎΠΏΡ€ΠΎΠ±ΡƒΠ΅ΠΌ Π²Ρ‹ΡΡΠ½ΠΈΡ‚ΡŒ, ΠΊΠ°ΠΊ это происходит:

        func race() {
    wait := make(chan struct{})
    n := 0
    go func() {
        n++ // Ρ‡Ρ‚Π΅Π½ΠΈΠ΅, ΡƒΠ²Π΅Π»ΠΈΡ‡Π΅Π½ΠΈΠ΅, запись
        close(wait)
    }()
    n++ // ΠΊΠΎΠ½Ρ„Π»ΠΈΠΊΡ‚ΡƒΡŽΡ‰ΠΈΠΉ доступ
    <-wait
    fmt.Println(n) // Π’Ρ‹Π²ΠΎΠ΄: <unspecified>
}
    

Π”Π²Π΅ Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Ρ‹ g1 ΠΈ g2, ΡƒΡ‡Π°ΡΡ‚Π²ΡƒΡŽΡ‚ Π² Π³ΠΎΠ½ΠΊΠ΅, ΠΈ Π½Π΅Ρ‚ Π½ΠΈΠΊΠ°ΠΊΠΎΠ³ΠΎ способа ΡƒΠ·Π½Π°Ρ‚ΡŒ, Π² ΠΊΠ°ΠΊΠΎΠΌ порядкС Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒΡΡ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ. НиТС ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½ ΠΎΠ΄ΠΈΠ½ ΠΈΠ· Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… Π²ΠΎΠ·ΠΌΠΎΠΆΠ½Ρ‹Ρ… Π²Π°Ρ€ΠΈΠ°Π½Ρ‚ΠΎΠ²:

πŸƒ ΠŸΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½ΠΎΠ΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ Π² Go

Как ΠΈΠ·Π±Π΅ΠΆΠ°Ρ‚ΡŒ Π³ΠΎΠ½ΠΊΠΈ Π΄Π°Π½Π½Ρ‹Ρ…?

ЕдинствСнный способ ΠΈΠ·Π±Π΅ΠΆΠ°Ρ‚ΡŒ Π³ΠΎΠ½ΠΊΠΈ – ΡΠΈΠ½Ρ…Ρ€ΠΎΠ½ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ доступ ΠΊΠΎ всСм mutable-Π΄Π°Π½Π½Ρ‹ΠΌ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ΡΡ ΠΏΠΎΡ‚ΠΎΠΊΠ°ΠΌΠΈ совмСстно. Π•ΡΡ‚ΡŒ нСсколько способов Π΄ΠΎΠ±ΠΈΡ‚ΡŒΡΡ этого. Π’ Go ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ ΠΊΠ°Π½Π°Π» ΠΈΠ»ΠΈ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠ° (Π½ΠΈΠ·ΠΊΠΎΡƒΡ€ΠΎΠ²Π½Π΅Π²Ρ‹Π΅ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌΡ‹ доступны Π² ΠΏΠ°ΠΊΠ΅Ρ‚Π°Ρ… sync ΠΈ sync/atomic).

ΠŸΡ€Π΅Π΄ΠΏΠΎΡ‡Ρ‚ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹ΠΉ способ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠ³ΠΎ доступа ΠΊ Π΄Π°Π½Π½Ρ‹ΠΌ Π² Go – ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΊΠ°Π½Π°Π» для ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ Π΄Π°Π½Π½Ρ‹Ρ… ΠΎΡ‚ ΠΎΠ΄Π½ΠΎΠΉ Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Ρ‹ ΠΊ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΉ.

        func sharingIsCaring() {
    ch := make(chan int)
    go func() {
        n := 0 // Π›ΠΎΠΊΠ°Π»ΡŒΠ½Π°Ρ пСрСмСнная Π²ΠΈΠ΄Π½Π° Ρ‚ΠΎΠ»ΡŒΠΊΠΎ для ΠΏΠ΅Ρ€Π²ΠΎΠΉ Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Ρ‹
        n++
        ch <- n // Π”Π°Π½Π½Ρ‹Π΅ ΠΎΡ‚ΠΏΡ€Π°Π²Π»ΡΡŽΡ‚ΡΡ ΠΈΠ· ΠΏΠ΅Ρ€Π²ΠΎΠΉ Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Ρ‹
    }()
    n := <-ch // ...ΠΈ Π±Π»Π°Π³ΠΎΠΏΠΎΠ»ΡƒΡ‡Π½ΠΎ ΠΏΡ€ΠΈΠ±Ρ‹Π²Π°ΡŽΡ‚ Π²ΠΎ Π²Ρ‚ΠΎΡ€ΡƒΡŽ
    n++
    fmt.Println(n) // Π’Ρ‹Π²ΠΎΠ΄: 2
}
    

Π’ этом ΠΊΠΎΠ΄Π΅ ΠΊΠ°Π½Π°Π»Π° происходят Π΄Π²Π° события:

  • ΠΏΠ΅Ρ€Π΅Π΄Π°ΡŽΡ‚ΡΡ Π΄Π°Π½Π½Ρ‹Π΅ ΠΎΡ‚ ΠΎΠ΄Π½ΠΎΠΉ Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Ρ‹ ΠΊ Π΄Ρ€ΡƒΠ³ΠΎΠΉ – Ρ‚ΠΎΡ‡ΠΊΠ° синхронизации;
  • ΠΎΡ‚ΠΏΡ€Π°Π²Π»ΡΡŽΡ‰Π°Ρ Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Π° Π±ΡƒΠ΄Π΅Ρ‚ ΠΆΠ΄Π°Ρ‚ΡŒ, ΠΏΠΎΠΊΠ° другая ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ Π΄Π°Π½Π½Ρ‹Π΅ ΠΈ Π½Π°ΠΎΠ±ΠΎΡ€ΠΎΡ‚.
МодСль памяти Go довольно слоТна: пСрСмСнная Π² ΠΎΠ΄Π½ΠΎΠΉ Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎ Π½Π°Π±Π»ΡŽΠ΄Π°Ρ‚ΡŒ значСния, ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π½Ρ‹Π΅ ΠΏΡ€ΠΈ записи Π² Ρ‚Ρƒ ΠΆΠ΅ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ Π² Π΄Ρ€ΡƒΠ³ΠΎΠΉ Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Π΅, Π½ΠΎ Π΄ΠΎ Ρ‚Π΅Ρ… ΠΏΠΎΡ€, ΠΏΠΎΠΊΠ° Π²Ρ‹ Π΄Π΅Π»ΠΈΡ‚Π΅ΡΡŒ всСми mutable-Π΄Π°Π½Π½Ρ‹ΠΌΠΈ ΠΌΠ΅ΠΆΠ΄Ρƒ Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Π°ΠΌΠΈ ΠΏΠΎ ΠΊΠ°Π½Π°Π»Π°ΠΌ, Π²Ρ‹ Π·Π°Ρ‰ΠΈΡ‰Π΅Π½Ρ‹ ΠΎΡ‚ Π³ΠΎΠ½ΠΊΠΈ Π΄Π°Π½Π½Ρ‹Ρ….

Как ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠΈΡ‚ΡŒ Π³ΠΎΠ½ΠΊΡƒ Π΄Π°Π½Π½Ρ‹Ρ…?

Π“ΠΎΠ½ΠΊΠΈ Π΄Π°Π½Π½Ρ‹Ρ… ΠΌΠΎΠ³ΡƒΡ‚ Π»Π΅Π³ΠΊΠΎ ΠΏΠΎΡΠ²Π»ΡΡ‚ΡŒΡΡ, Π½ΠΎ ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠΈΡ‚ΡŒ ΠΈΡ… Ρ‚Ρ€ΡƒΠ΄Π½ΠΎ. К ΡΡ‡Π°ΡΡ‚ΡŒΡŽ срСда выполнСния Go ΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΠΎΠΌΠΎΡ‡ΡŒ ΠΈ Π² этом. Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ ΠΊΠ»ΡŽΡ‡ -race для Π²ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ встроСнного Π΄Π΅Ρ‚Π΅ΠΊΡ‚ΠΎΡ€Π° Π³ΠΎΠ½ΠΊΠΈ Π΄Π°Π½Π½Ρ‹Ρ….

        $ go test -race [packages]
$ go run -race [packages]
    

ΠŸΡ€ΠΈΠΌΠ΅Ρ€

ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° с Π³ΠΎΠ½ΠΊΠΎΠΉ Π΄Π°Π½Π½Ρ‹Ρ…:

        package main
import "fmt"

func main() {
    i := 0
    go func() {
        i++ // запись
    }()
    fmt.Println(i) // ΠΊΠΎΠ½ΠΊΡƒΡ€Π΅Π½Ρ‚Π½ΠΎΠ΅ Ρ‡Ρ‚Π΅Π½ΠΈΠ΅
}
    

Запуск этой ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ с ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠΌ -race ΠΏΠΎΠΊΠ°ΠΆΠ΅Ρ‚ Π½Π°ΠΌ, Ρ‡Ρ‚ΠΎ сущСствуСт Π³ΠΎΠ½ΠΊΠ° ΠΌΠ΅ΠΆΠ΄Ρƒ записью Π² строкС 7 ΠΈ Ρ‡Ρ‚Π΅Π½ΠΈΠ΅ΠΌ Π² строкС 9:

        $ go run -race main.go
0
==================
WARNING: DATA RACE
Write by goroutine 6:
  main.main.func1()
      /tmp/main.go:7 +0x44

Previous read by main goroutine:
  main.main()
      /tmp/main.go:9 +0x7e

Goroutine 6 (running) created at:
  main.main()
      /tmp/main.go:8 +0x70
==================
Found 1 data race(s)
exit status 66
    

ΠŸΠΎΠ΄Ρ€ΠΎΠ±Π½ΠΎΡΡ‚ΠΈ

Π”Π΅Ρ‚Π΅ΠΊΡ‚ΠΎΡ€ Π³ΠΎΠ½ΠΊΠΈ Π½Π΅ выполняСт Π½ΠΈΠΊΠ°ΠΊΠΎΠ³ΠΎ статичСского Π°Π½Π°Π»ΠΈΠ·Π°. Он провСряСт доступ ΠΊ памяти Π²ΠΎ врСмя выполнСния Ρ‚ΠΎΠ»ΡŒΠΊΠΎ для фактичСски Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‰Π΅Π³ΠΎ ΠΊΠΎΠ΄Π°.

Он Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ Π½Π° darwin/amd64, freebsd/amd64, linux/amd64 ΠΈ Windows/amd64.

НакладныС расходы Π²Π°Ρ€ΡŒΠΈΡ€ΡƒΡŽΡ‚ΡΡ, Π½ΠΎ ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ происходит ΡƒΠ²Π΅Π»ΠΈΡ‡Π΅Π½ΠΈΠ΅ использования памяти Π² 5-10 Ρ€Π°Π· ΠΈ ΡƒΠ²Π΅Π»ΠΈΡ‡Π΅Π½ΠΈΠ΅ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ выполнСния Π² 2-20 Ρ€Π°Π·.

Как ΠΎΡ‚Π»Π°ΠΆΠΈΠ²Π°Ρ‚ΡŒ deadlock-ΠΈ

Дэдлоки Π²ΠΎΠ·Π½ΠΈΠΊΠ°ΡŽΡ‚, ΠΊΠΎΠ³Π΄Π° Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Ρ‹ ΠΆΠ΄ΡƒΡ‚ Π΄Ρ€ΡƒΠ³ Π΄Ρ€ΡƒΠ³Π° ΠΈ Π½ΠΈ ΠΎΠ΄Π½Π° ΠΈΠ· Π½ΠΈΡ… Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π·Π°Π²Π΅Ρ€ΡˆΠΈΡ‚ΡŒΡΡ.

ВзглянСм Π½Π° ΠΏΡ€ΠΈΠΌΠ΅Ρ€:

        func main() {
	ch := make(chan int)
	ch <- 1
	fmt.Println(<-ch)
}
    

ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° застрянСт Π½Π° ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠΈ, оТидая Π²Π΅Ρ‡Π½ΠΎ, ΠΏΠΎΠΊΠ° ΠΊΡ‚ΠΎ-Ρ‚ΠΎ ΠΏΡ€ΠΎΡ‡ΠΈΡ‚Π°Π΅Ρ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅. Go способСн ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠΈΠ²Π°Ρ‚ΡŒ ΠΏΠΎΠ΄ΠΎΠ±Π½Ρ‹Π΅ ситуации Π²ΠΎ врСмя выполнСния. Π’ΠΎΡ‚ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ нашСй ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹:

        fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan send]:
main.main()
	.../deadlock.go:7 +0x6c
    

Π‘ΠΎΠ²Π΅Ρ‚Ρ‹ ΠΏΠΎ ΠΎΡ‚Π»Π°Π΄ΠΊΠ΅

Π“ΠΎΡ€ΡƒΡ‚ΠΈΠ½Π° ΠΌΠΎΠΆΠ΅Ρ‚ Π·Π°ΡΡ‚Ρ€ΡΡ‚ΡŒ:

  • ΠΊΠΎΠ³Π΄Π° ΠΎΠ½Π° ΠΆΠ΄Π΅Ρ‚ ΠΊΠ°Π½Π°Π»;
  • Π»ΠΈΠ±ΠΎ ΠΊΠΎΠ³Π΄Π° ΠΎΠ½Π° ΠΆΠ΄Π΅Ρ‚ ΠΎΠ΄Π½Ρƒ ΠΈΠ· Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΎΠΊ Π² ΠΏΠ°ΠΊΠ΅Ρ‚Π΅ sync.

ΠžΠ±Ρ‰ΠΈΠ΅ ΠΏΡ€ΠΈΡ‡ΠΈΠ½Ρ‹:

  • Π½ΠΈ ΠΎΠ΄Π½Π° Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Π° Π½Π΅ ΠΈΠΌΠ΅Π΅Ρ‚ доступа ΠΊ ΠΊΠ°Π½Π°Π»Ρƒ ΠΈΠ»ΠΈ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠ΅;
  • Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Ρ‹ ΠΆΠ΄ΡƒΡ‚ Π΄Ρ€ΡƒΠ³ Π΄Ρ€ΡƒΠ³Π°.
БСйчас Go ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠΈΠ²Π°Π΅Ρ‚ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ зависаниС всСй ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ Π² Ρ†Π΅Π»ΠΎΠΌ, Π° Π½Π΅ ΠΊΠΎΠ³Π΄Π° застрСваСт Π½Π΅ΠΊΠΎΠ΅ подмноТСство Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½.

Π‘ ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΊΠ°Π½Π°Π»ΠΎΠ² Π»Π΅Π³ΠΊΠΎ ΠΏΠΎΠ½ΡΡ‚ΡŒ, Ρ‡Ρ‚ΠΎ Π²Ρ‹Π·Π²Π°Π»ΠΎ Π΄Π΅Π΄Π»ΠΎΠΊ. Π‘ Π΄Ρ€ΡƒΠ³ΠΎΠΉ стороны, интСнсивно ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‰ΠΈΠ΅ ΠΌΡŒΡŽΡ‚Π΅ΠΊΡΡ‹ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ Π·Π°Π²Π΅Π΄ΠΎΠΌΠΎ Ρ‚Ρ€ΡƒΠ΄Π½Ρ‹ΠΌΠΈ для ΠΎΡ‚Π»Π°Π΄ΠΊΠΈ.

ОТиданиС Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½

Π“Ρ€ΡƒΠΏΠΏΠ° sync.WaitGroup ΠΎΠΆΠΈΠ΄Π°Π΅Ρ‚ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ Ρ€Π°Π±ΠΎΡ‚Ρ‹ Π³Ρ€ΡƒΠΏΠΏΡ‹ Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½:

        var wg sync.WaitGroup
wg.Add(2)
go func() {
    // Do work.
    wg.Done()
}()
go func() {
    // Do work.
    wg.Done()
}()
wg.Wait()
    
  • сначала основная Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Π° Π²Ρ‹Π·Ρ‹Π²Π°Π΅Ρ‚ Add, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ количСство ΠΎΠΆΠΈΠ΄Π°ΡŽΡ‰ΠΈΡ… Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½;
  • Π·Π°Ρ‚Π΅ΠΌ Π·Π°ΠΏΡƒΡΠΊΠ°ΡŽΡ‚ΡΡ Π΄Π²Π΅ Π½ΠΎΠ²Ρ‹Π΅ Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Ρ‹ ΠΈ Π²Ρ‹Π·Ρ‹Π²Π°ΡŽΡ‚ Done ΠΏΡ€ΠΈ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΠΈ.

Π’ Ρ‚ΠΎ ΠΆΠ΅ врСмя Wait ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ для Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ Π΄ΠΎ Ρ‚Π΅Ρ… ΠΏΠΎΡ€, ΠΏΠΎΠΊΠ° эти Π΄Π²Π΅ Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Ρ‹ Π½Π΅ Π·Π°Π²Π΅Ρ€ΡˆΠ°Ρ‚ΡΡ.

Π—Π°ΠΌΠ΅Ρ‡Π°Π½ΠΈΠ΅: Π³Ρ€ΡƒΠΏΠΏΠ° оТидания Π½Π΅ Π΄ΠΎΠ»ΠΆΠ½Π° ΠΊΠΎΠΏΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒΡΡ послС ΠΏΠ΅Ρ€Π²ΠΎΠ³ΠΎ использования.

Врансляция сигнала ΠΏΠΎ ΠΊΠ°Π½Π°Π»Ρƒ

Π’ этом ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ функция Publish Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ ΠΊΠ°Π½Π°Π», ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ для ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ сигнала ΠΏΡ€ΠΈ ΠΏΡƒΠ±Π»ΠΈΠΊΠ°Ρ†ΠΈΠΈ сообщСния.

        // ΠΏΠ΅Ρ‡Π°Ρ‚ΡŒ тСкста ΠΏΠΎ истСчСнии Π·Π°Π΄Π°Π½Π½ΠΎΠ³ΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ
// ΠΊΠΎΠ³Π΄Π° это Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ, ΠΊΠ°Π½Π°Π» оТидания Π±ΡƒΠ΄Π΅Ρ‚ Π·Π°ΠΊΡ€Ρ‹Ρ‚
func Publish(text string, delay time.Duration) (wait <-chan struct{}) {
    ch := make(chan struct{})
    go func() {
        time.Sleep(delay)
        fmt.Println("BREAKING NEWS:", text)
        close(ch) // трансляция Π½Π° всС ΠΏΡ€ΠΈΠ΅ΠΌΠ½ΠΈΠΊΠΈ
    }()
    return ch
}
    

ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, Ρ‡Ρ‚ΠΎ ΠΌΡ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ ΠΊΠ°Π½Π°Π» пустых структур: struct{}. Π­Ρ‚ΠΎ явно ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ Π½Π° Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ ΠΊΠ°Π½Π°Π» ΠΏΡ€Π΅Π΄Π½Π°Π·Π½Π°Ρ‡Π΅Π½ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ для сигнализации, Π° Π½Π΅ для ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ Π΄Π°Π½Π½Ρ‹Ρ….

Π’ΠΎΡ‚ ΠΊΠ°ΠΊ ΠΌΠΎΠΆΠ½ΠΎ это ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ:

        func main() {
    wait := Publish("Channels let goroutines communicate.", 5*time.Second)
    fmt.Println("Waiting for news...")
    <-wait
    fmt.Println("Time to leave.")
}
    
        Waiting for news...
BREAKING NEWS: Channels let goroutines communicate.
Time to leave.
    

Как ΡƒΠ±ΠΈΡ‚ΡŒ Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Ρƒ

Π§Ρ‚ΠΎΠ±Ρ‹ Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Π° ΠΎΡΡ‚Π°Π½ΠΎΠ²ΠΈΠ»Π°ΡΡŒ, Π΅ΠΉ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΠΏΡ€ΠΎΡΠ»ΡƒΡˆΠΈΠ²Π°Ρ‚ΡŒ сигнал остановки Π½Π° Π²Ρ‹Π΄Π΅Π»Π΅Π½Π½ΠΎΠΌ Π²Ρ‹Ρ…ΠΎΠ΄Π½ΠΎΠΌ ΠΊΠ°Π½Π°Π»Π΅ ΠΈ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΡΡ‚ΡŒ Π΅Π³ΠΎ.

        quit := make(chan bool)
go func() {
    for {
        select {
        case <-quit:
            return
        default:
            // …
        }
    }
}()
// …
quit <- true
    

Π’ΠΎΡ‚ Π±ΠΎΠ»Π΅Π΅ ΠΏΠΎΠ»Π½Ρ‹ΠΉ ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Π³Π΄Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ ΠΎΠ΄ΠΈΠ½ ΠΊΠ°Π½Π°Π» ΠΊΠ°ΠΊ для ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ Π΄Π°Π½Π½Ρ‹Ρ…, Ρ‚Π°ΠΊ ΠΈ для сигнализации:

        // Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ ΠΊΠ°Π½Π°Π», ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚ числа 1, 2, 3…
// Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΎΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ ΠΎΡΠ½ΠΎΠ²Π½ΡƒΡŽ Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Ρƒ, Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΈΡ‚ΡŒ 
// Π½ΠΎΠΌΠ΅Ρ€ этому ΠΊΠ°Π½Π°Π»Ρƒ
func Generator() chan int {
    ch := make(chan int)
    go func() {
        n := 1
        for {
            select {
            case ch <- n:
                n++
            case <-ch:
                return
            }
        }
    }()
    return ch
}

func main() {
    number := Generator()
    fmt.Println(<-number)
    fmt.Println(<-number)
    number <- 0           // остановка основной Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Ρ‹
    fmt.Println(<-numberΠΌ) // ошибка, большС Π½ΠΈΠΊΡ‚ΠΎ Π½Π΅ отправляСт
   
}
    
        1
2
fatal error: all goroutines are asleep - deadlock!
    

Timer ΠΈ Ticker

Π’Π°ΠΉΠΌΠ΅Ρ€Ρ‹ ΠΈ Ρ‚ΠΈΠΊΠ΅Ρ€Ρ‹ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‚ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒ ΠΊΠΎΠ΄ ΠΏΠΎ Ρ€Π°ΡΠΏΠΈΡΠ°Π½ΠΈΡŽ ΠΎΠ΄ΠΈΠ½ ΠΈΠ»ΠΈ нСсколько Ρ€Π°Π·.

Timeout (Timer)

time.After ΠΎΠΆΠΈΠ΄Π°Π΅Ρ‚ Π² Ρ‚Π΅Ρ‡Π΅Π½ΠΈΠ΅ Π·Π°Π΄Π°Π½Π½ΠΎΠ³ΠΎ ΠΏΡ€ΠΎΠΌΠ΅ΠΆΡƒΡ‚ΠΊΠ°, Π° Π·Π°Ρ‚Π΅ΠΌ отправляСт Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π΅ врСмя ΠΏΠΎ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΠΎΠΌΡƒ ΠΊΠ°Π½Π°Π»Ρƒ:

        select {
case news := <-AFP:
	fmt.Println(news)
case <-time.After(time.Hour):
	fmt.Println("No news in an hour.")
}
    

time.Timer Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Π°Π½ сборщиком мусора Π΄ΠΎ Ρ‚Π΅Ρ… ΠΏΠΎΡ€, ΠΏΠΎΠΊΠ° Ρ‚Π°ΠΉΠΌΠ΅Ρ€ Π½Π΅ сработаСт. Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ time.NewTimer вмСсто Π²Ρ‹Π·ΠΎΠ²Π° ΠΌΠ΅Ρ‚ΠΎΠ΄Π° Stop, ΠΊΠΎΠ³Π΄Π° Ρ‚Π°ΠΉΠΌΠ΅Ρ€ большС Π½Π΅ Π½ΡƒΠΆΠ΅Π½:

        for alive := true; alive; {
	timer := time.NewTimer(time.Hour)
	select {
	case news := <-AFP:
		timer.Stop()
		fmt.Println(news)
	case <-timer.C:
		alive = false
		fmt.Println("No news in an hour. Service aborting.")
	}
}
    

Repeat (Ticker)

time.Tick Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ ΠΊΠ°Π½Π°Π», ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ обСспСчиваСт Ρ‚ΠΈΠΊΠ°Π½ΡŒΠ΅ часов с Ρ‡Π΅Ρ‚Π½Ρ‹ΠΌΠΈ ΠΈΠ½Ρ‚Π΅Ρ€Π²Π°Π»Π°ΠΌΠΈ:

        go func() {
	for now := range time.Tick(time.Minute) {
		fmt.Println(now, statusUpdate())
	}
}()
    

time.Ticker Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Π°Π½ сборщиком мусора Π΄ΠΎ Ρ‚Π΅Ρ… ΠΏΠΎΡ€, ΠΏΠΎΠΊΠ° Ρ‚Π°ΠΉΠΌΠ΅Ρ€ Π½Π΅ сработаСт. Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ time.NewTicker вмСсто Π²Ρ‹Π·ΠΎΠ²Π° ΠΌΠ΅Ρ‚ΠΎΠ΄Π° Stop, ΠΊΠΎΠ³Π΄Π° Ρ‚ΠΈΠΊΠ΅Ρ€ большС Π½Π΅ Π½ΡƒΠΆΠ΅Π½:

        func Foo() {
    timer = time.AfterFunc(time.Minute, func() {
        log.Println("Foo run for more than a minute.")
    })
    defer timer.Stop()

    // Do heavy work
}
    

Π‘Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠ° Π²Π·Π°ΠΈΠΌΠ½ΠΎΠ³ΠΎ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ (ΠΌΡŒΡŽΡ‚Π΅ΠΊΡ)

Иногда ΡƒΠ΄ΠΎΠ±Π½Π΅Π΅ ΡΠΈΠ½Ρ…Ρ€ΠΎΠ½ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ доступ ΠΊ Π΄Π°Π½Π½Ρ‹ΠΌ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ явной Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ, Π° Π½Π΅ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΊΠ°Π½Π°Π»ΠΎΠ². Бтандартная Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° Go ΠΏΡ€Π΅Π΄Π»Π°Π³Π°Π΅Ρ‚ для этой Ρ†Π΅Π»ΠΈ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΡƒ Π²Π·Π°ΠΈΠΌΠ½ΠΎΠ³ΠΎ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ sync.Mutex.

Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ с ΠΎΡΡ‚ΠΎΡ€ΠΎΠΆΠ½ΠΎΡΡ‚ΡŒΡŽ

Π§Ρ‚ΠΎΠ±Ρ‹ этот Ρ‚ΠΈΠΏ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ Π±Ρ‹Π» бСзопасным, ΠΊΡ€Π°ΠΉΠ½Π΅ Π²Π°ΠΆΠ½ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ всС обращСния ΠΊ ΠΎΠ±Ρ‰ΠΈΠΌ Π΄Π°Π½Π½Ρ‹ΠΌ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΠ»ΠΈΡΡŒ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ‚ΠΎΠ³Π΄Π°, ΠΊΠΎΠ³Π΄Π° Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Π° находится Π² Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠ΅. Одной ошибки Π² ΠΎΠ΄Π½ΠΎΠΉ Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Π΅ достаточно, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ввСсти Π³ΠΎΠ½ΠΊΡƒ Π΄Π°Π½Π½Ρ‹Ρ… ΠΈ ΡΠ»ΠΎΠΌΠ°Ρ‚ΡŒ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ.

Из-Π·Π° этого Π²Π°ΠΌ слСдуСт ΠΏΠΎΠ΄ΡƒΠΌΠ°Ρ‚ΡŒ ΠΎ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ΅ кастомной структуры Π΄Π°Π½Π½Ρ‹Ρ… с чистым API ΠΈ ΡƒΠ±Π΅Π΄ΠΈΡ‚ΡŒΡΡ, Ρ‡Ρ‚ΠΎ вся синхронизация выполняСтся Π²Π½ΡƒΡ‚Ρ€ΠΈ.

Π’ этом ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ ΠΌΡ‹ создаСм Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΡƒΡŽ ΠΈ ΠΏΡ€ΠΎΡΡ‚ΡƒΡŽ Π² использовании ΠΊΠΎΠ½ΠΊΡƒΡ€Π΅Π½Ρ‚Π½ΡƒΡŽ структуру Π΄Π°Π½Π½Ρ‹Ρ… AtomicInt, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ хранится integer. Π›ΡŽΠ±ΠΎΠ΅ количСство Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½ ΠΌΠΎΠΆΠ΅Ρ‚ бСзопасно ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ доступ ΠΊ этому числу с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ² Add ΠΈ Value.

        // AtomicInt – это ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½Π°Ρ структура Π΄Π°Π½Π½Ρ‹Ρ…, содСрТащая int
// Π΅Π³ΠΎ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Ρ€Π°Π²Π½ΠΎ 0
type AtomicInt struct {
    mu sync.Mutex // Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠ° ΠΌΠΎΠΆΠ΅Ρ‚ ΡƒΠ΄Π΅Ρ€ΠΆΠΈΠ²Π°Ρ‚ΡŒΡΡ ΠΎΠ΄Π½ΠΎΠΉ Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½ΠΎΠΉ Π·Π° Ρ€Π°Π·
    n  int
}

// добавляСт n ΠΊ AtomicInt
func (a *AtomicInt) Add(n int) {
    a.mu.Lock() //  ΠΆΠ΄Π΅ΠΌ ΠΏΠΎΠΊΠ° Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠ° освободится
    a.n += n
    a.mu.Unlock() // освобоТдСниС Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ
}

// Value Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ a
func (a *AtomicInt) Value() int {
    a.mu.Lock()
    n := a.n
    a.mu.Unlock()
    return n
}

func main() {
    wait := make(chan struct{})
    var n AtomicInt
    go func() {
        n.Add(1) // ΠΎΠ΄ΠΈΠ½ доступ
        close(wait)
    }()
    n.Add(1) // Π΄Ρ€ΡƒΠ³ΠΎΠΉ ΠΊΠΎΠ½ΠΊΡƒΡ€Π΅Π½Ρ‚Π½Ρ‹ΠΉ доступ
    <-wait
    fmt.Println(n.Value()) // 2
}
    

Π—Π°ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅

ΠœΡ‹ рассмотрСли распространСнныС ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹, относящиСся ΠΊ конкурСнтности Π² Go. Π­Ρ‚ΠΎ Π½Π΅ вСсь ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π» ΠΏΠΎ Ρ‚Π΅ΠΌΠ΅ – ΠΎΡΡ‚Π°Π»ΡŒΠ½ΠΎΠ΅ Π²Π°ΠΌ придСтся ΡΠ°ΠΌΠΎΡΡ‚ΠΎΡΡ‚Π΅Π»ΡŒΠ½ΠΎ ΠΈΠ·ΡƒΡ‡Π°Ρ‚ΡŒ Π½Π° ΠΎΡ„ΠΈΡ†ΠΈΠ°Π»ΡŒΠ½ΠΎΠΌ сайтС. НС Π»Π΅Π½ΠΈΡ‚Π΅ΡΡŒ, Ρ€Π°Π·Π²ΠΈΠ²Π°ΠΉΡ‚Π΅ΡΡŒ ΠΈ ΡƒΠ΄Π°Ρ‡ΠΈ Π² ΠΎΠ±ΡƒΡ‡Π΅Π½ΠΈΠΈ!

Π”ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»Ρ‹:



Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊΠΈ

ΠšΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΈ

 
 

Π›Π£Π§Π¨Π˜Π• БВАВЬИ ПО Π’Π•ΠœΠ•

LIVE >

Подпишись

Π½Π° push-увСдомлСния