Go-рутины — это легковесный управляемый поток. Go-рутины запускаются в одинаковых адресных пространствах, так что доступ к общей памяти должен быть синхронизирован. Пакет sync предоставляет примитивы, однако в Go и есть другие подходы.
packagemainimport"fmt"funcprintHello() { fmt.Println("Hello from printHello")}funcmain() {// Встроенная Go-рутинаgofunc() { fmt.Println("Hello from inline") }()// Функция как Go-рутинаgoprintHello()// Функция в главном потокеprintln("Hello from main")}
Если вызвать такую программу, выведется в консоль только Hello from main, так как main-функция не дождалась выполнения go-рутины. Тут нам понадобятся каналы:
packagemainimport"fmt"// Печатает на стандартный вывод и отправляет int в каналfuncprintHello(ch chanint) { fmt.Println("Hello from printHello")// Посылает значение в канал ch <-2}funcmain() {// Создаем канал. Для этого нам нужно использовать функцию make// Каналы могут быть буферизированными с заданным размером:// ch := make(chan int, 2), но это выходит за рамки данной статьи. ch :=make(chanint)// Встроенная горутина. Определим функцию, а затем вызовем ее.// Запишем в канал по её завершениюgofunc(){ fmt.Println("Hello inline")// Отправляем значение в канал ch <-1 }()// Вызываем функцию как горутинуgoprintHello(ch) fmt.Println("Hello from main")// Получаем первое значение из канала// и сохраним его в переменной, чтобы позже распечатать i :=<- ch fmt.Println("Received ",i)// Получаем второе значение из канала// и не сохраняем его, потому что не будем использовать<- ch}
sync.Mutex
Для блокирования каких-то объектов для горутин (для синхронизации).
Пример запуска операций в несколько потоков (горутин)