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

Чтобы использовать эту функцию, просто введите ключевое слово 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. Мы можем понимать эту концепцию как канал или проводник, отвечающий за отправку данных между процессами. Давайте обновим наш код, чтобы затем использовать channels.

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. Быть chan затем он инициализируется в основной функции и передается в goroutines.

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