Новости

24.08.2020

Книга «Golang для профи: работа с сетью, многопоточность, структуры данных и машинное обучение с Go»

Изучая нюансы Go, вы освоите типы и структуры данных языка, а также работу с пакетами, конкурентность, сетевое программирование, устройство компиляторов, оптимизацию и многое другое. Закрепить новые знания помогут материалы и упражнения в конце каждой главы. Уникальным материалом станет глава о машинном обучении на языке Go, в которой вы пройдёте от основополагающих статистических приемов до регрессии и кластеризации. Вы изучите классификацию, нейронные сети и приёмы выявления аномалий. Из прикладных разделов вы узнаете: как использовать Go с Docker и Kubernetes, Git, WebAssembly, JSON и др.

И снова о Go-каналах


Как только задействуется ключевое слово select, появляется несколько уникальных способов использования Go-каналов, позволяющих сделать гораздо больше, чем то, что вы видели в главе 9. В этом разделе вы узнаете о разных способах использования Go-каналов.

Напомню, что нулевым значением для каналов является nil, и если отправить сообщение в закрытый канал, то программа перейдет в режим паники. Но если вы попытаетесь прочитать данные из закрытого канала, то получите нулевое значение для данного типа канала. Таким образом, после закрытия канала вы больше не можете записывать в него данные, но все равно можете читать его.

Чтобы канал можно было закрыть, он не должен быть предназначен только для приема данных. Кроме того, нулевой канал всегда блокируется, то есть попытка чтения или записи с нулевого канала заблокирует канал. Это свойство каналов очень полезно в тех случаях, когда нужно отключить ветвь оператора select, — для этого достаточно присвоить переменной канала значение nil.

Наконец, при попытке закрыть нулевой канал программа поднимет панику. Рассмотрим это на примере программы closeNilChannel.go:

Выполнение closeNilChannel.go приведет к следующему результату:

Сигнальные каналы


Сигнальный канал — это канал, который применяется только для передачи сигналов. Проще говоря, сигнальный канал можно использовать в тех случаях, когда вы хотите проинформировать другую программу о чем-либо. К сигнальным каналам не нужно прибегать для передачи данных.

Не следует путать сигнальные каналы с обработкой сигналов UNIX, о которой говорилось в главе 8, это совершенно разные вещи.

Пример кода, в котором используются сигнальные каналы, мы рассмотрим далее в этой главе.

Буферизованные каналы


Тема этого подраздела — буферизованные каналы. Это каналы, которые позволяют планировщику Go быстро размещать задания в очереди, чтобы обрабатывать больше запросов. Кроме того, их можно использовать в качестве семафоров, позволяющих ограничить пропускную способность приложения.

Представленный здесь метод работает так: все входящие запросы перенаправляются на канал, который обрабатывает их по очереди. Когда канал завершает обработку запроса, он отправляет исходному вызывающему объекту сообщение о том, что канал готов обработать новый запрос. Таким образом, емкость буфера канала ограничивает количество одновременных запросов, которые этот канал может хранить.

Мы рассмотрим этот метод на примере кода программы bufChannel.go. Разделим его на четыре части.

Первая часть кода bufChannel.go выглядит так:

Второй фрагмент файла bufChannel.go содержит следующий код Go:

Представленное здесь определение numbers позволяет хранить в этом канале до пяти целых чисел.

В третьей части bufChannel.go содержится следующий код Go:

 

В этом коде мы попытались поместить в канал numbers десять чисел. Однако, поскольку в numbers есть место только для пяти целых чисел, сохранить в нем все десять целых чисел нам не удастся.

Остальной код Go из файла bufChannel.go выглядит так:

В этом коде Go мы попытались прочитать содержимое канала numbers с помощью цикла for и оператора select. Пока в канале numbers есть что читать, будет выполняться первая ветвь оператора select. Когда канал numbers пустой, выполняется ветвь default.

Выполнение bufChannel.go приведет к результату следующего вида:

Нулевые каналы


В этом разделе вы познакомитесь с нулевыми каналами. Это особый вид каналов, который всегда блокирован. Мы рассмотрим эти каналы на примере программы nilChannel.go. Разделим ее на четыре фрагмента кода.

Первая часть nilChannel.go выглядит так:

Во второй части nilChannel.go содержится следующий код Go:

Здесь на примере функции add() показано, как используется нулевой канал. Оператор <-t.C блокирует канал C таймера t на время, указанное в вызове time.NewTimer(). Не путайте канал c, который является аргументом функции, с каналом t.C, который принадлежит таймеру t. По истечении времени таймер отправляет значение в канал t.C, чем инициирует выполнение соответствующей ветви оператора select — он присваивает каналу c значение nil и выводит на экран значение переменной sum.

Третий фрагмент кода nilChannel.go выглядит так:

Цель функции send() — генерировать случайные числа и отправлять их в канал до тех пор, пока канал открыт.

Остальной код Go в nilChannel.go выглядит так:

Функция time.Sleep() нужна для того, чтобы у двух горутин было достаточно времени для выполнения.

Запуск nilChannel.go приведет к следующим результатам:

Поскольку количество выполнений первой ветви оператора select в функции add() не является фиксированным, запустив nilChannel.go несколько раз, мы получим разные результаты.

С полным содержанием статьи можно ознакомиться на сайте "Хабрахабр": https://habr.com/ru/company/piter/blog/514518/


Комментарии: 0

Пока нет комментариев


Оставить комментарий






Все поля обязательны к заполнению.

Перед публикацией комментарии проходят модерацию.