Знакомство с Go: что это за язык и стоит ли его изучать?
Go — это высокоуровневый язык программирования с открытым исходным кодом, на котором можно создавать надежные и при этом простые программы.
Go разрабатывался в компании Google с 2007-го года и уже в 2009-м году был представлен официально. Это выразительный, компактный язык с понятным синтаксисом, что упрощает создание программ.
Благодаря механизмам параллелизма этот язык позволяет пользоваться преимуществами многоядерных и сетевых компьютеров.
Несмотря на то, что это компилируемый язык со статической типизацией, с ним так же легко работать, как и с интерпретируемым языком с динамической типизацией. Go поддерживают ОС Linux, Windows, macOS, OpenBSD, DragonFly BSD, FreeBSD, NetBSD, Solaris.
Синтаксис Go
Синтаксис Go напоминает синтаксис C. Некоторые элементы заимствованы из языка Оберон и скриптовых языков. Это регистрозависимый язык. В идентификаторах и строках полностью поддерживается Юникод.
Чтобы получить базовое представление о синтаксисе Go, разберем простую программу:
package main import "fmt" // The entry point func main() { fmt.Println("Привет, Go!") }
Вначале необходимо определить имя пакета. Это делается с помощью ключевого слова package
:
package main
Программы на Go состоят из пакетов. Пакет — это набор исходных файлов, которые находятся в одном и том же каталоге и компилируются вместе.
Функции, типы, переменные и константы, определенные в одном исходном файле пакета, доступны во всех остальных исходных файлах этого пакета.
Пакет main используется для создания исполняемого двоичного файла. Выполнение программы начинается с вызова функции main
из этого пакета.
Один пакет можно импортировать в другой. Для этого используется ключевое слово import
. За ним указывается имя импортируемого пакета в кавычках:
import "fmt"
Следующая строка содержит комментарий. В Go используются комментарии в стиле C. В этом примере видим строчный комментарий, который начинается с двух косых черт (// ...)
. Блочные комментарии из нескольких строк вставляются между /*
и */
. Компилятор воспринимает строчный комментарий и блочный комментарий из нескольких строк как перевод строки, а однострочный блочный — как пробел.
Определение функции main
:
func main() { fmt.Println("Привет, Go!") }
Оно начинается с ключевого слова func
, за которым следует имя функции, список аргументов в скобках (скобки ставятся и при отсутствии аргументов) и открывающая фигурная скобка. В следующих строках располагается код тела функции, за которым в отдельной строке ставится закрывающая фигурная скобка.
Стиль напоминает С, но есть некоторые важные отличия. Обратите внимание на положение открывающей фигурной скобки и на отсутствие точки с запятой после единственной строки в теле функции.
В отличие от языка C, точка с запятой в Go используется редко: в некоторых случаях в операторах if
, for
и switch
, а также для разделения команд, помещенных в одной строке. Компилятор сам расставляет точки с запятой в конце строк, поэтому нужно запомнить, что перенос строки допустим не в любом месте, где можно использовать пробел. Например, в объявлениях функций необходимо ставить фигурную скобку после круглой, завершающей список аргументов:
func a(){ }
Если бы фигурная скобка располагалась на следующей строке, то компилятор вставил бы запятую после закрывающей круглой скобки:
func a(); { }
По той же причине ключевое слово else
следует располагать в одной строке с закрывающей фигурной скобкой после if
, иначе точка с запятой появилась бы после этой скобки:
if condition { ... }; else { ... }
Код тела функции состоит из единственной строки, которая выводит строку «Привет, Go!» и переводит курсор на следующую строку:
fmt.Println("Привет, Go!")
В этой строке мы вызываем функцию Println
из пакета fmt. Для этого сначала указываем имя пакета, затем через точку — имя функции, а в скобках приводим строковой аргумент в прямых двойных кавычках. Двоеточие после вызова функции не ставим, потому что его подставит компилятор.
Сохраните код из начала раздела в файле hello.go и запустите программу в командной строке или терминале:
go run hello.go
После недолгой компиляции будет выведен результат:
Теперь расширим возможности этой маленькой программы: научим ее «обращаться» к пользователю по имени.
Ознакомьтесь с кодом:
package main import ( "fmt" "os" ) func main() { var name string fmt.Print("Как тебя зовут? ") fmt.Fscan(os.Stdin, &name) fmt.Println("Привет,", name + "!") }
Чтобы ввести имя пользователя с консоли, воспользуемся функцией Fscan
из пакета os. Для этого в текущий код нужно добавить еще одно объявление импорта. Можно вставить еще одну строку:
import "fmt" import "os"
Такой вид импорта называется прямым. Но рекомендуется использовать более удобный способ — групповой:
import ( "fmt" "os" )
При его использовании код выглядит понятнее и не приходится каждый раз указывать ключевое слово import
.
В первой строке тела функции объявляем переменную строкового типа. Для этого используем ключевое слово var
, после него через разделитель укажем имя переменной, после чего определим ее тип (тоже через разделитель):
var name string
По умолчанию строковая переменная получает значение пустой строки. Если нужно инициализировать переменную, ее значение можно указать в объявлении:
var name string = "No name"
Далее выведем запрос на ввод имени:
fmt.Print("Как тебя зовут? ")
Для вывода используется команда Print
, которая работает так же, как и Println
, но не переводит строку. После запроса в строке оставлен пробел, чтобы отделить запрос от ввода.
Далее считаем ввод в переменную name
из стандартного ввода os.Stdin
:
fmt.Fscan(os.Stdin, &name)
Теперь по адресу (&
) переменной name
находится введенный текст.
Выведем приветствие на экран:
fmt.Println("Привет,", name + "!")
Если в функции Println
указано несколько аргументов, то они выводятся через пробел, поэтому перед закрывающей кавычкой здесь пробел не ставим. Второй аргумент получаем с помощью конкатенации — «сложения» строк.
Вывод будет выглядеть так:
Пришло время подробнее рассмотреть использованные в примерах возможности языка.
Импорт в Go
В Go используется несколько типов импорта.
Типы импорта в Go | ||
Пример | Описание | Использование в коде |
import "fmt" |
Прямой импорт. В кавычках указывается путь к пакету. Для встроенных пакетов указывается только их имена. Также можно указывать пути в интернете, например: github.com/<username>/<package> |
fmt.Print("Go") |
import ( "fmt" "os" )
|
Групповой импорт. | os.Stdin |
import "math/rand" |
Вложенный импорт. Используется, когда нужно воспользоваться только подмножеством функций пакета. | rand.Int(100) |
import f "fmt" |
Импорт с псевдонимом | f.Println("Go") |
import . "math" |
Импорт без указания имени пакета (квалификации). Используется, в основном, для тестирования публичных элементов. Может вызвать конфликт пространства имен. | Sin(1.0) |
import _ "math" |
Пустой импорт. Если пакет импортирован, но не используется, то в Go возникает ошибка. Чтобы она не возникала, используется пустой импорт. Когда потребуется воспользоваться пакетом, определение импорта можно будет заменить другим. |
Типы данных в Go
Мы уже упоминали выше, что в Go используется статическая типизация. Тип переменной определяется в объявлении и его невозможно изменить впоследствии. Это позволяет избежать некоторых распространенных ошибок.
Рассмотрим встроенные типы данных.
Числовые типы
Целые числа | |
Тип | Описание |
uint8 и byteuint16 uint32 uint64 |
Беззнаковые целые числа. Принимают только неотрицательные значения. 8, 16, 32 и 64 — это количество бит, которое отведено на число соответствующего типа. |
int8 int16 int32 и rune int64 |
Знаковые целые числа. |
uint int uintptr |
Машинно-зависимые целочисленные типы. |
Вещественные числа | |
Тип | Описание |
float32 | С одинарной точностью |
float64 | С двойной точностью |
Еще существуют значения NaN (not a number) для результатов таких вычислений, как 0/0, а также положительная и отрицательная бесконечность (+∞ и −∞).
Комплексные числа | |
Тип | Описание |
complex64 | Вещественная и мнимая части представлены числами с типом float32 |
complex128 | Вещественная и мнимая части представлены числами с типом float64 |
Над числами в Go можно производить приведенные ниже операции.
Операции над числами в Go | |
+ | сложение |
– | вычитание |
* | умножение |
/ | деление |
% | остаток от деления |
Важно знать, что Go не поддерживает неявное приведение типов. Поэтому операции можно проводить только над данными одного и того же типа.
Строки
Строки в Go представляют собой неизменяемые последовательности символов UTF-8. Они заключаются в двойные кавычки или в обратные галочки.
В строках в двойных кавычках можно использовать управляющие символы, такие как \r
, \t
.
Строки в обратных галочках являются «сырыми» литералами. Они не поддерживают управляющие символы, но могут состоять из нескольких строк и содержать любые символы, кроме обратной галочки. Обычно они используются для многострочных сообщений, в регулярных выражениях и HTML.
Строки могут быть пустыми, но пустые строки не являются нулевыми.
Для строк предусмотрена операция конкатенации, как мы уже видели во втором примере кода. Для нее используется тот же оператор, что и для сложения (+
).
Чтобы узнать количество символов в строке, независимо от кодировки, используется функция RuneCountInString()
из пакета UTF-8. Функция len()
возвращает число байтов в строке.
Важно помнить, что строки неизменяемы, и попытка изменить строку приводит к ошибке.
Булевский тип
Это однобайтовый целочисленный тип, значения которого представляют истинность и ложность (соответственно true
и false
).
Для этого типа предусмотрены три оператора:
Логические операторы | |
&& | и |
|| | или |
! | не |
В Go поддерживаются также массивы, представляющие собой последовательности элементов одного типа.
Переменные и присваивание в Golang
Объявление переменной начинается с ключевого слова var
, после разделителя указывается имя переменной, а за ним после разделителя — тип:
var x int32
После объявления переменных разных типов они получают нулевые значения: все числовые типы — 0, строковые — пустую строку, указатели — nil.
После объявления переменной можно присвоить ей значение. Для явного присваивания значений переменной с заданным типом используется символ =
:
x = 100
Присвоить переменной значение можно и в объявлении. Инициализация переменной с указанием типа производится так:
var y string = "Hello"
Поскольку в Go поддерживается автоматический вывод типов, при инициализации можно не указывать тип переменной:
var z = true
Локальные переменные можно объявлять и инициализировать с помощью сокращенной формы записи и оператора :=
:
n = 20
Если нужно объявить несколько переменных, можно заключить их объявления в скобки:
var ( firstName string = "Luke" lastName string = "Skywalker" )
При объявлении массива перед типом в квадратных скобках указывается количество элементов:
var numbers [5]int
Константы
Константы в Go бывают типизированные и нетипизированные. Типизированные константы объявляются так же, как и переменные с инициализацией, только с использованием ключевого слова const
:
const pi float64 = 3.1415
Нетипизированная константа определяется без указания типа:
const a = 1
После этого объявления значение 1 не отнесено к какому-либо типу. Это просто целочисленное значение. Оно может использоваться в операциях с целыми числами.
Управляющие конструкции в Go
Условные конструкции
Конструкция if…elseпринимает выражение, которое возвращает булевское значение. Если возвращено значение true
, то выполняется блок кода в фигурных скобках, следующий за конструкцией:
if x > 0 { fmt.Println("x - положительное") }
Если в приведенном выше примере кода значение x окажется больше нуля, то в консоли будет выведена строка. В противном случае управление будет передано коду, следующему за закрывающей фигурной скобкой.
Если нужно, чтобы один код выполнялся при истинном значении условного выражения, а другой — при ложном, используется ключевое слово else
:
if x > 0 { fmt.Println("x - положительное") } else { fmt.Println("x - не положительное") }
Условия можно «нанизывать»:
if x > 0 { fmt.Println("x - положительное") } else if x < 0 { fmt.Println("x - отрицательное") } else { fmt.Println("x - ноль") }
Если требуется сравнить некоторое выражение с набором значений и в каждом случае выполнить соответствующие действия, используется конструкция switch:
switch(n) { case 1: fmt.Println("n = 1") case 2: fmt.Println("n = 2") case 3, 4: // несколько значений fmt.Println("n = 3 или 4") default: // если не совпало с указанными значениями fmt.Println("значение n не соответствует предусмотренным")
Циклы
В Go есть только один цикл — for.Он имеет следующую структуру:
for [инициализация;] [условие;] [приращение] { // действия }
Например:
for i = 1; i < 10; i++ { fmt.Println(i * i) }
В этом цикле выводятся квадраты чисел от 1 до 9. Вначале счетчик получает значение 1 и при каждой итерации оно увеличивается на единицу. Итерации прекращаются по достижении счетчиком значения 10.
Необязательно указывать все условия. При этом нужно предусмотреть инициализацию и приращение значения счетчика, а также условие выхода из цикла:
i = 0 for{ if i < 5 { continue } else if i > 9 { break } fmt.Println(i * i) }
Этот цикл выведет квадраты чисел от 5 до 9 включительно. Пока значение счетчика будет меньше 5, ключевое слово continue
не будет передавать управление строке, которая выводит значение на экран. Начиная со значения 5 значение будет выводиться, а когда счетчик получит значение 10, ключевое слово break
осуществит выход из цикла.
Функции в Go
Объявление функции в Go:
func имя (параметры) (типы_возвращаемых_значений){ операторы }
Функция, не возвращающая значение:
func hello() { fmt.Println("Hello!") }
Для возврата значения из функции используется оператор return
и указывается тип возвращаемого значения:
func add (a int, b int) int { return a + b }
Возвращаемое значение может быть именованным:
func add (a int, b int) (z int) { z = a + b return }
Поскольку переменная z определена как возвращаемое значение, ее не приходится указывать после оператора return
.
Функция может возвращать несколько значений:
func addmul (a, b int) (int, int) { c = a + b d = a * b return c, d } x, y = addmul(2, 5)
Эти результаты также могут быть именованными:
func addmul (a, b int) (c, d int) { c = a + b d = a * b return }
Поскольку в Go не только пакеты, но и объявленные переменные обязательно должны использоваться в программе, предусмотрена псевдопеременная _
. Она позволяет проигнорировать возвращаемое значение.
Например, если нужно получить только результат сложения, следующий код выдаст ошибку:
x = addmul(2, 5)
Псевдопеременная позволяет избежать ошибки:
x, _ = addmul(2, 5)
Отложенный вызов и обработка ошибок
В Golang не реализованы обработчики исключительных ситуаций. Вместо них и блоков с гарантированным завершением используется ключевое слово defer
. Указанная после него функция будет выполнена по завершении функции, в которой используется эта конструкция:
func main() { defer deferred() fmt.Println("Программа запущена") } func deferred(){ fmt.Println("Выполнение программы завершено") }
Несмотря на то, что функция, выводящая строку «Программа запущена», находится в конце функции main
, она будет вызвана первой из двух строк тела функции.
Оператор panic
используется для генерирования ошибки и выхода из программы. Ему можно передать строку, которая будет выведена в консоли. Кроме этой строки выводится диагностическая информация. Перед завершением программы выполняются все функции, вызванные ключевым словом defer
.
Выполним такую программу:
package main import "fmt" func main () { defer bye() fmt.Println(div(8, 2)) fmt.Println(div(8, 0)) } func div (a, b float32) float32 { if b == 0 { panic("Попытка деления на ноль.") } return a/b } func bye () { fmt.Println("Пока!") }
В результате ее выполнения в консоли будет выведено число 4, строка «Пока!» и сообщение об ошибке:
Многопоточность в Go
Поток программы создается ключевым словом go
. Оно запускает функцию в новой сопрограмме. В Go такие сопрограммы называются go-процедурами. Они выполняются параллельно. При использовании многоядерных процессоров эти процедуры могут выполняться на разных ядрах, что ускоряет работу программы.
Go-процедуры экономны по сравнению с нитями. Размер их стека составляет лишь несколько килобайт, и он может изменяться в зависимости от требований приложения.
Рассмотрим простой пример использования go-процедур:
package main import ( "fmt" ) func hello() { fmt.Println("Hello from goroutine") } func main() { go hello() fmt.Println("Hello from main function") }
Программа создает go-процедуру, которая может вывести в консоли приветствие Hello from goroutine, затем выводит приветствие Hello from main function. Запустим программу в консоли несколько раз:
Как видим, результаты разные. Иногда первой выводится строка из go-процедуры, иногда — из функции main
, а при последнем вызове строка из go-процедуры не выводится вовсе. Дело в том, что когда завершается выполнение функции main
, завершается и работа всей программы, в том числе всех go-процедур. После вызова go-процедуры вызвавшая ее функция продолжает работу. Если go-процедура успевает выполнить свою работу перед завершением работы программы, выводится соответствующая строка. Если же нет — эта строка не выводится.
Чтобы сделать результаты более предсказуемыми, добавим перед строкой вывода в функции main
еще одну строку, в которой будет считываться ввод из консоли:
package main import ( "fmt" ) func hello() { fmt.Println("Hello from goroutine") } func main() { go hello() fmt.Scanln() fmt.Println("Hello from main function") }
В результате получим:
Go-процедуры обмениваются данными через каналы. Для их создания используется ключевое слово chan
с указанием типа элемента. Переменная для канала, по которому передаются целые числа, определяется таким образом:
var intChannel chan int
Теперь по нему можно передавать числа с помощью оператора <-
:
intChannel <- 7 // передаем данные в канал intValue := <- intChannel // получаем данные из канала
После определения канала приведенным выше способом он не инициализирован и имеет значение nil
. Чтобы его инициализировать, нужно воспользоваться функцией make()
.
Каналы бывают буферизированные и небуферизированные. Для создания небуферизированного канала используется функция make()
без указания аргументов (емкости канала):
var intChannel chan int = make(chan int)
Также можно воспользоваться выводом типов:
intChannel := make(chan int)
Процедура-получатель работает только тогда, когда в канале есть данные. Когда канал пуст, ее работа блокируется. Процедура-отправитель передает данные в канал, когда он пуст. После отправки данных ее работа блокируется до получения данных из канала. Чтобы продемонстрировать работу с каналами, запустим следующий код:
package main import "fmt" func main() { intChannel := make(chan int) fmt.Println("Функция main запускает Go-процедуру.") go func(){ fmt.Println("Go-процедура отправляет данные в канал.") fmt.Println("Ее работа блокируется.") intChannel <- 10 fmt.Println("Данные переданы в канал.") fmt.Println("Go-процедура разблокирована.") }() // В качестве go-процедур можно использовать замыкания intResult := <-intChannel fmt.Println("Функция main получила данные из канала:", intResult) }
Вывод программы будет выглядеть так:
В этой статье дано только базовое представление о синтаксисе языка Go и рассмотрены некоторые его особенности. Подробнее о языке можно узнать из документации.
Примеры использования
Рассмотрим примеры кода, в которых используются конструкции языка Go, с которыми вы познакомились выше.
В первом примере будем использовать функции из нескольких модулей, условные конструкции, цикл, два вида присваивания, псевдопеременную. Код не требует отдельных пояснений — читайте комментарии:
/* Основы синтаксиса Go на примере программы для угадывания числа */ // Объявление пакета package main // Импорт модулей, необходимых для работы программы import ( "fmt" "os" "math/rand" "time" ) // Точка входа (отсюда начинается выполнение программы) func main() { // Переменная для загаданного числа var secret int // Переменная для номера попытки var attempt int = 0 // Флаг завершения игры var isOver bool = false // Число пользователя var number int = 0 var win bool = false // Получим порождающий элемент с автоматическим выводом типа (:=) seed := time.Now().UnixNano() // Зададим порождающий элемент rand.Seed(seed) // Получим случайное число и присвоим его переменной явно (=) secret = rand.Intn(1024) + 1 // Выведем приглашение fmt.Println("Отгадайте целое число от 1 до 1024.") fmt.Println("Для выхода введите 0.") fmt.Println() // Начнем бесконечный цикл с выходом при условии истинности isOver for { attempt++ fmt.Print("Введите число: ") _, err := fmt.Fscan(os.Stdin, &number) // Проверим, введено ли допустимое число if err != nil { fmt.Println("Вводите только целые числа!") attempt-- continue } // Проанализируем ввод if number == 0 { // Команда выхода? isOver = true } else if number == secret { // Число угадано? win = true isOver = true } else if number < secret { // Догадка меньше загаданного? fmt.Println("Маловато будет!") } else { // Значит, догадка больше загаданного fmt.Println("Многовато будет!") } if isOver { // Постусловие выхода break } } // Флаг выхода установлен в true // Выведем сообщение о результате if win { fmt.Println("Вы угадали число за", attempt, "попыток.") } fmt.Println("До свидания!") }
Результат выполнения выглядит примерно так:
Во втором примере продемонстрируем использование go-процедуры и каналов. Программа запросит, на сколько секунд запустить таймер, и будет вести обратный отсчет, каждую секунду выводя оставшееся время, пока не сработает таймер:
package main import ( "fmt" "os" "time" ) func main() { seconds := 0 fmt.Print("На сколько секунд запустить таймер? ") fmt.Fscan(os.Stdin, &seconds) counter := seconds timer := time.NewTimer(time.Duration(seconds) * time.Second) ticker := time.NewTicker(time.Second) fmt.Println(counter) go func(){ for { select { case <- ticker.C: counter-- fmt.Println(counter) case <- timer.C: return } } }() time.Sleep(time.Duration(seconds) * time.Second) fmt.Println("Время вышло") }
Где используется Go
- Компания Google, в которой разработан Go, использует этот язык для своих внутренних проектов. В частности, на нем созданы Google Cloud и Kubernetes.
- Многие сервисы Uber также написаны на Go. С развитием компании использовалось все больше ресурсов и повышалась задержка. Для повышения эффективности компания переписала на Go код, который ранее был написан на Python.
- В видеостриминговом сервие Twitch язык Go используется для самых загруженных систем, в том числе для прямой трансляции видео и одновременного обслуживания множества чатов.
- Облачная служба хранения данных Dropbox использует Go, чтобы эффективно управлять взаимодействием с более чем 500 миллионами пользователей.
- Компания Dailymotion обеспечила с помощью этого языка автоматизацию API.
- Облачный сервис электронной почты SendGrid использует Go как основной язык программирования. С его помощью отправляются подтверждения покупок, предложения, обрабатываются входящие сообщения и перенаправляются запросы клиентов.
- Компания SoundCloud выбрала Go для проведения статического анализа в режиме реального времени и ускорения работы над приложениями.
- Платформа блогов и публикаций Medium использует Go для обработки изображений.
- BBC применяет Go для разработки серверной части приложений, в том числе для социальных сетей и мобильных устройств.
- Компания Docker предпочитает этот язык благодаря возможностям, которые он дает для разработки крупномасштабных распределенных проектов, в том числе статической компиляции без зависимостей, надежной стандартной библиотеке, полнофункциональной среде разработки и возможности компоновать приложения для различных архитектур с минимальными трудностями.
В целом язык Go используется благодаря тому, что он позволяет повысить эффективность приложений, обеспечить многопоточную обработку данных, сократить затраты времени и усилий на разработку приложений.
Преимущества Go
- Go — быстрый язык. Go — это компилируемый язык. Написанный на нем код преобразуется в код, понятный процессору. Благодаря этому он работает быстрее, чем такие языки, как Java и Python, что повышает доступность и надежность служб.
- Язык Go легко освоить. Если у вас есть опыт программирования на C или Java, то вам будет легко освоить Go. Несмотря на некоторые различия, в Go используется же самый процедурный подход, и вам не придется тратить много времени на знакомство с ним.
- Go экономно использует память. Go-процедуры — это функции, которые выполняются одновременно и независимо друг от друга. Одна процедура занимает всего два килобайта памяти, что очень удобно, когда необходимо одновременно выполнять очень много процессов. Эти процедуры не являются блокирующими, как нити в Java. В них скомбинирован асинхронный подход, как в JavaScript, и традиционная многопоточность, как в Java. Но нити занимают большие объемы памяти, в то время как можно запустить миллионы компактных go-процедур без сбоев в работе системы.
- Статическая типизация. Благодаря статической типизации в Go сводится к минимуму риск ошибок, которые допускаются по невнимательности. Go выдаст ошибку, если переменной попытаются присвоить значение не того типа, который ей назначен. Это упрощает и ускоряет процесс разработки.
Недостатки Go
Несмотря на растущую популярность Go, он не идеален, как исключительная ситуация любой другой язык программирования:
- Требует много времени. Программисту может понадобиться написать десятки строк кода, чтобы реализовать ту же функцию, которую на Python можно уместить в паре строк. Это замедляет процесс разработки программного обеспечения.
- Это молодой язык. Программисты, которые только начинают осваивать Go, столкнутся с проблемами работы с существующими библиотеками, особенно при взаимодействии с другими платформами. Для связывания нескольких программ потребуется писать лишний код.
- Go не поддерживает обобщенные функции. Обобщенные функции — это коллекция различных функций с одним и тем же именем, но с неопределенными типами входных данных на момент компиляции. Без поддержки таких функций программистам потребуется создавать множество функций, которые принимают разные параметры. Из-за этого ограничивается возможность повторного использования кода и снижается эффективность разработки.
Резюме
Язык Go предназначен для создания крупных распределенных проектов, которые работают на многоядерных процессорах. Программы на нем выполняются без использования виртуальной машины и быстро компилируются, обеспечивая интерактивную разработку.
Поскольку это компилируемый язык, многие компании переписывают на нем свое программное обеспечение. Это делается, чтобы ускорить обработку информации, в том числе за счет параллельных процессов.
В ситуациях, когда скорость разработки и компактность кода важнее, чем скорость выполнения программ, лучше использовать более удобный с этой точки зрения язык, например Python.
Тем не менее, Go популярен в таких сферах, как бэкенд-разработка, веб-разработка, базы данных, финансовые услуги, медиа, а чаще всего он применяется в технологическом секторе. Этот язык продолжает развиваться, и ожидается выпуск его второй версии. К тому же, он прост в изучении. Поэтому знакомство с ним не займет много времени и будет полезным. Удачи!
Сообщить об опечатке
Текст, который будет отправлен нашим редакторам: