Одной из лучших особенностей Go является простота использования параллелизма. Язык дает нам goroutines, которые похожи на легкие потоки, управляемые средой выполнения Go. Это помогает нам запускать несколько функций одновременно и очень полезно, если вы хотите повысить производительность своего приложения.

Использовать эту функцию просто, добавив go ключевое слово перед любым вызовом функции. Это заставит функцию работать одновременно. Чтобы было проще, давайте покажем вам код. Вот я и написал SleepSort алгоритм, который использует sleep метод сортировки каждого элемента на своем месте.

package main

import (
    "fmt"
    "time"
)

func main() {
    arr := []int{3, 1, 5, 6, 9, 2, 0}

    fmt.Println("Sorting", arr)
    for _, v := range arr {
        go Sort(v)
    }
}

func Sort(x int) {
    time.Sleep(time.Duration(x) * time.Second)
    fmt.Printf("%d ", x)
}
Войти в полноэкранный режим

Выйти из полноэкранного режима

В этом коде у нас есть sort функция, которая спит в течение x секунд и печатает значение. Когда каждая функция завершит свое выполнение, у нас будет массив в правильном порядке, верно? К сожалению, нет!

Ответ в начале

Поскольку функции выполняются одновременно с основным процессом, мы видим только то, что основной должен вернуть. Один из способов решить эту проблему — заставить все процессы каким-то образом взаимодействовать с основным процессом. Для этого иди дай нам channel концепция, которая похожа на канал/канал, отвечающий за отправку данных между процессами. Давайте обновим наш код, чтобы использовать эту функцию!

package main

import (
    "fmt"
    "time"
)

func main() {
    arr := []int{3, 1, 5, 6, 9, 2, 0}
    c := make(chan int)

    fmt.Println("Sorting", arr)
    for _, v := range arr {
        go sort(v, c)
    }

    fmt.Println("Sorted:")
    for range arr {
        x := <-c
        fmt.Printf("%d ", x)
    }
}

func sort(x int, c chan int) {
    time.Sleep(time.Duration(x) * time.Second)
    c <- x
}
Войти в полноэкранный режим

Выйти из полноэкранного режима

И, наконец, у нас есть ответ:

Ответ после представления каналов

Мы можем заметить, что channels есть специальный оператор <-. Чтобы понять, как это работает, мы должны думать об этом как о стрелке. Данные всегда будут течь туда, куда указывает стрелка. Например, внутри функции sortданные передаются по каналу с помощью c <- x и основной процесс получает его и присваивает новой переменной, используя x := <-c.

Также важно сказать, что нам пришлось изменить sort сигнатура функции была обновлена, чтобы принять chan. Он инициализируется в основной функции, а затем передается в goroutines.

Как мы видим, начать использовать параллелизм в Go довольно просто. Язык также поддерживает более продвинутые параметры, но мы поговорим об этом в следующем посте блога. Если вам нравится тема, вы также можете найти меня на Твиттер, Гитхабили же LinkedIn. Вы также можете найти этот текст в португальский.